@instruments/materialgraph 2.0.0 → 2.2.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/catalog-client.d.ts +1 -6
- package/catalog-client.js +0 -15
- package/catalog-types.d.ts +0 -43
- package/colors-client.d.ts +1 -1
- package/colors-client.js +6 -2
- package/find-sampled-together-types.d.ts +0 -2
- package/get-variant-types.d.ts +1 -1
- package/index.d.ts +1 -2
- package/nearest-paints-types.d.ts +2 -0
- package/operation-responses.d.ts +1 -4
- package/operations.generated.d.ts +1 -1
- package/operations.generated.js +0 -12
- package/package.json +1 -5
- package/resolve-color-types.d.ts +0 -6
- package/response-schemas.generated.d.ts +1 -1
- package/response-schemas.generated.js +36 -40
- package/search-catalog-subset-types.d.ts +1 -1
- package/webmcp.generated.js +4 -4
- package/samplize-catalog-types.d.ts +0 -98
- package/samplize-catalog-types.js +0 -1
- package/samplize-colorvec.d.ts +0 -70
- package/samplize-colorvec.js +0 -222
|
@@ -43,7 +43,7 @@ import type { OpenEnum } from "./types.js";
|
|
|
43
43
|
* that were never in the Material Bank feed; if you mean orderable, use one of
|
|
44
44
|
* the channel-backed scopes above.
|
|
45
45
|
*/
|
|
46
|
-
export type SearchCatalogSubset = OpenEnum<"
|
|
46
|
+
export type SearchCatalogSubset = OpenEnum<"samplizeOrderable" | "all" | "designShopOrderable" | "materialBankEuOrderable" | "materialBankNaAndCatalog" | "materialBankNaOrderable" | "materialBankOrderable">;
|
|
47
47
|
/**
|
|
48
48
|
* The corpus a response AND its counts were drawn from. Present only when a
|
|
49
49
|
* narrowing scope applied — absence means the whole graph. Read it alongside
|
package/webmcp.generated.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const json = [
|
|
2
|
-
"[{\"annotations\":{\"readOnlyHint\":true,\"untrustedContentHint\":true},\"description\":\"Reads `query` into filters, runs them through `list_variants` and answers with what was understood beside a page of variants. `understood` says what each phrase became: a hard `filter`, a ranking `preference`, or `not_applied` when nothing could serve it. `filters`, `optionalFilters` and `name` are exactly what ran, so the three can be sent to `list_variants` to narrow or widen the same search. A phrase with more than one meaning is answered with one and listed in `choices`: send its `handle` with an alternative's `group` and `id` in `selections` to switch it. `unresolved` lists words nothing in the vocabulary could read. A query that applies nothing returns no items, never the whole catalog; a preference alone still ranks it. `cursor` is the previous page's `pageInfo.endCursor`, tied to the vocabulary version the query was read against; it pages this operation only, not `list_variants`. Requires the `mg:read` bearer scope.\",\"inputSchema\":{\"$ref\":\"#/$defs/schema0\",\"$defs\":{\"schema0\":{\"type\":\"object\",\"properties\":{\"attributes\":{\"description\":\"Attribute/block ids to add; id fields always return.\",\"maxItems\":50,\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"cursor\":{\"type\":\"string\"},\"leaveOut\":{\"maxItems\":8,\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"limit\":{\"description\":\"5-10 for examples.\",\"type\":\"integer\",\"minimum\":1,\"maximum\":50},\"query\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":200,\"description\":\"What to find, in plain words.\"},\"searchCatalogSubset\":{\"description\":\"Only this corpus scope.\",\"type\":\"string\",\"enum\":[\"all\",\"
|
|
3
|
-
"},\"image\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"alt\":{\"type\":\"string\"},\"url\":{\"type\":\"string\"}},\"required\":[\"alt\",\"url\"],\"additionalProperties\":false},{\"type\":\"null\"}],\"description\":\"The settled material card image. Always null for paint color samples and paint/coating product types.\"},\"brand\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"}},\"required\":[\"id\",\"name\"],\"additionalProperties\":false,\"description\":\"The brand. `id` is the slug get_brand takes.\"},\"name\":{\"type\":\"string\",\"description\":\"The unambiguous variant name, including its source label when needed.\"},\"variantLabel\":{\"description\":\"The source variant label, trimmed; null when unknown or for a paint color sample, whose own name identifies its color. Separate from surface finish, color family and derived color names.\",\"type\":[\"string\",\"null\"]},\"product\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"}},\"required\":[\"id\",\"name\"],\"additionalProperties\":false},\"url\":{\"description\":\"The brand's page for it, or null when none is known.\",\"type\":[\"string\",\"null\"]},\"variantId\":{\"type\":\"string\"},\"materialBankId\":{\"description\":\"The variant's Material Bank SKU. Absent: none recorded.\",\"type\":\"string\"},\"notApplicable\":{\"type\":\"object\",\"properties\":{\"attributes\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"blocks\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"additionalProperties\":false,\"description\":\"Requested blocks or attributes this product type does not carry.\"},\"preference\":{\"type\":\"object\",\"properties\":{\"matched\":{\"type\":\"array\",\"items\":{\"type\":\"number\"}},\"score\":{\"type\":\"number\"}},\"required\":[\"matched\",\"score\"],\"additionalProperties\":false},\"specifications\":{\"type\":\"object\",\"propertyNames\":{\"type\":\"string\"},\"additionalProperties\":{\"type\":\"object\",\"propertyNames\":{\"type\":\"string\"},\"additionalProperties\":{\"$ref\":\"#/$defs/schema1\"}}},\"variantCount\":{\"description\":\"Eligible variants of this product. Absent: none counted.\",\"type\":\"integer\",\"exclusiveMinimum\":0,\"maximum\":9007199254740991}},\"required\":[\"category\",\"categories\",\"productType\",\"sampleSubject\",\"colorOptionValueId\",\"hasDeclaredColor\",\"code\",\"brand\",\"name\",\"variantLabel\",\"product\",\"variantId\"],\"additionalProperties\":false}},\"nameWords\":{\"description\":\"Empty name lookup: each word, and whether a name in scope starts it. Unmatched words were left out unless all or none matched.\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"matched\":{\"type\":\"boolean\"},\"word\":{\"type\":\"string\"}},\"required\":[\"matched\",\"word\"],\"additionalProperties\":false}},\"pageInfo\":{\"type\":\"object\",\"properties\":{\"endCursor\":{\"type\":[\"string\",\"null\"]},\"hasNextPage\":{\"type\":\"boolean\"}},\"required\":[\"endCursor\",\"hasNextPage\"],\"additionalProperties\":false},\"preferenceMatchesRemain\":{\"description\":\"False: nothing from this page on meets any optionalFilter.\",\"type\":\"boolean\"},\"unavailableVariantIds\":{\"description\":\"Filtered ids in the catalog this list can't show, e.g. retired.\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"unresolvedVariantIds\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"unstated\":{\"description\":\"Filtered attributes no variant in scope states at all.\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"words\":{\"description\":\"Each word asked for, and whether any variant in scope names it.\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"matched\":{\"type\":\"boolean\"},\"word\":{\"type\":\"string\"}},\"required\":[\"matched\",\"word\"],\"additionalProperties\":false}},\"choices\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"alternatives\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"group\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"},\"kind\":{\"type\":\"string\"},\"label\":{\"type\":\"string\"}},\"required\":[\"group\",\"id\",\"kind\",\"label\"],\"additionalProperties\":false}},\"basis\":{\"type\":\"string\"},\"handle\":{\"type\":\"string\"},\"reason\":{\"type\":\"string\"},\"selected\":{\"type\":\"object\",\"properties\":{\"group\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"},\"kind\":{\"type\":\"string\"},\"label\":{\"type\":\"string\"}},\"required\":[\"group\",\"id\",\"kind\",\"label\"],\"additionalProperties\":false},\"text\":{\"type\":\"string\"}},\"
|
|
4
|
-
"
|
|
5
|
-
"}}},\"additionalProperties\":false,\"description\":\"The preferences that ran.\"},\"outcome\":{\"type\":\"string\",\"enum\":[\"page\",\"partial_match\",\"no_match\",\"nothing_understood\",\"out_of_scope\",\"brand_not_in_catalog\"],\"description\":\"How the search ended.\"},\"scope\":{\"type\":\"object\",\"properties\":{\"anyField\":{\"description\":\"One of values in any of fields (term attributes).\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"fields\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"unstated\":{\"type\":\"string\",\"const\":\"pass\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"fields\",\"op\",\"values\"],\"additionalProperties\":false}},\"numbers\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"eq\",\"gt\",\"gte\",\"lt\",\"lte\"]},\"value\":{\"type\":\"number\"}},\"required\":[\"field\",\"op\",\"value\"],\"additionalProperties\":false}},\"presence\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"exists\",\"missing\"]}},\"required\":[\"field\",\"op\"],\"additionalProperties\":false}},\"terms\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"all\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"unstated\":{\"type\":\"string\",\"const\":\"pass\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"field\",\"op\",\"values\"],\"additionalProperties\":false}}},\"additionalProperties\":false,\"description\":\"The fixed scope, repeated in filters.\"},\"understood\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"applied\":{\"type\":\"string\",\"enum\":[\"filter\",\"preference\",\"not_applied\"],\"description\":\"filter narrows; preference only ranks; not_applied did neither.\"},\"id\":{\"type\":\"string\",\"description\":\"The parser's condition id.\"},\"kind\":{\"type\":\"string\",\"enum\":[\"category\",\"brand\",\"term\",\"number\",\"color\",\"paint\",\"name\",\"scope\"]},\"label\":{\"type\":\"string\",\"description\":\"What the words were read as.\"},\"note\":{\"type\":\"string\"},\"text\":{\"type\":\"string\",\"description\":\"The query words it came from.\"}},\"required\":[\"applied\",\"id\",\"kind\",\"label\",\"text\"],\"additionalProperties\":false}},\"unresolved\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"items\",\"pageInfo\",\"oneRowPer\",\"outcome\",\"understood\"],\"additionalProperties\":false}}},\"path\":\"/api/v1/variants/search\",\"requiredHeaders\":[],\"requiresVisibleConfirmation\":false}]",
|
|
2
|
+
"[{\"annotations\":{\"readOnlyHint\":true,\"untrustedContentHint\":true},\"description\":\"Reads `query` into filters, runs them through `list_variants` and answers with what was understood beside a page of variants. `understood` says what each phrase became: a hard `filter`, a ranking `preference`, or `not_applied` when nothing could serve it. `filters`, `optionalFilters` and `name` are exactly what ran, so the three can be sent to `list_variants` to narrow or widen the same search. A phrase with more than one meaning is answered with one and listed in `choices`: send its `handle` with an alternative's `group` and `id` in `selections` to switch it. `unresolved` lists words nothing in the vocabulary could read. A query that applies nothing returns no items, never the whole catalog; a preference alone still ranks it. `cursor` is the previous page's `pageInfo.endCursor`, tied to the vocabulary version the query was read against; it pages this operation only, not `list_variants`. Requires the `mg:read` bearer scope.\",\"inputSchema\":{\"$ref\":\"#/$defs/schema0\",\"$defs\":{\"schema0\":{\"type\":\"object\",\"properties\":{\"attributes\":{\"description\":\"Attribute/block ids to add; id fields always return.\",\"maxItems\":50,\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"cursor\":{\"type\":\"string\"},\"leaveOut\":{\"maxItems\":8,\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"limit\":{\"description\":\"5-10 for examples.\",\"type\":\"integer\",\"minimum\":1,\"maximum\":50},\"query\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":200,\"description\":\"What to find, in plain words.\"},\"searchCatalogSubset\":{\"description\":\"Only this corpus scope.\",\"type\":\"string\",\"enum\":[\"all\",\"samplizeOrderable\",\"materialBankOrderable\",\"materialBankNaOrderable\",\"materialBankNaAndCatalog\",\"materialBankEuOrderable\",\"designShopOrderable\"]},\"selections\":{\"description\":\"Switch a choice: handle, alternative group and id.\",\"maxItems\":8,\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"group\":{\"type\":\"string\"},\"handle\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"}},\"required\":[\"group\",\"handle\",\"id\"],\"additionalProperties\":false}},\"include\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"image\",\"url\"]}}},\"required\":[\"query\"],\"additionalProperties\":false}}},\"method\":\"POST\",\"name\":\"search\",\"operationId\":\"search_variants\",\"outputSchema\":{\"$ref\":\"#/$defs/schema0\",\"$defs\":{\"schema1\":{\"anyOf\":[{\"type\":\"string\"},{\"type\":\"number\"},{\"type\":\"boolean\"},{\"type\":\"null\"},{\"type\":\"array\",\"items\":{\"$ref\":\"#/$defs/schema1\"}},{\"type\":\"object\",\"propertyNames\":{\"type\":\"string\"},\"additionalProperties\":{\"$ref\":\"#/$defs/schema1\"}}]},\"schema0\":{\"type\":\"object\",\"properties\":{\"excludedBySearchCatalogSubset\":{\"description\":\"Filtered variant ids outside the materials catalog.\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"items\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"category\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"}},\"required\":[\"id\",\"name\"],\"additionalProperties\":false},{\"type\":\"null\"}],\"description\":\"The first original source category, or null when unknown.\"},\"categories\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"}},\"required\":[\"id\",\"name\"],\"additionalProperties\":false},\"description\":\"All original source categories in source order.\"},\"productType\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"}},\"required\":[\"id\",\"name\"],\"additionalProperties\":false},{\"type\":\"null\"}],\"description\":\"The accepted primary specification type, or null for a color sample or unresolved subject.\"},\"sampleSubject\":{\"type\":\"string\",\"enum\":[\"material\",\"paint_color_sample\",\"unknown\",\"conflict\"]},\"colorOptionValueId\":{\"type\":[\"string\",\"null\"]},\"hasDeclaredColor\":{\"type\":\"boolean\",\"description\":\"True for a paint color card, paint line, primer or coating: the card is the brand's declared hex, never a photo.\"},\"code\":{\"description\":\"The brand's item code.\",\"type\":[\"string\",\"null\"]},\"hex\":{\"description\":\"The settled card color hex, or null when unknown. Paint cards show this color and never a photo.\",\"type\":[\"string\",\"null",
|
|
3
|
+
"\"]},\"image\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"alt\":{\"type\":\"string\"},\"url\":{\"type\":\"string\"}},\"required\":[\"alt\",\"url\"],\"additionalProperties\":false},{\"type\":\"null\"}],\"description\":\"The settled material card image. Always null for paint color samples and paint/coating product types.\"},\"brand\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"}},\"required\":[\"id\",\"name\"],\"additionalProperties\":false,\"description\":\"The brand. `id` is the slug get_brand takes.\"},\"name\":{\"type\":\"string\",\"description\":\"The unambiguous variant name, including its source label when needed.\"},\"variantLabel\":{\"description\":\"The source variant label, trimmed; null when unknown or for a paint color sample, whose own name identifies its color. Separate from surface finish, color family and derived color names.\",\"type\":[\"string\",\"null\"]},\"product\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"}},\"required\":[\"id\",\"name\"],\"additionalProperties\":false},\"url\":{\"description\":\"The brand's page for it, or null when none is known.\",\"type\":[\"string\",\"null\"]},\"variantId\":{\"type\":\"string\"},\"materialBankId\":{\"description\":\"The variant's Material Bank SKU. Absent: none recorded.\",\"type\":\"string\"},\"notApplicable\":{\"type\":\"object\",\"properties\":{\"attributes\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"blocks\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"additionalProperties\":false,\"description\":\"Requested blocks or attributes this product type does not carry.\"},\"preference\":{\"type\":\"object\",\"properties\":{\"matched\":{\"type\":\"array\",\"items\":{\"type\":\"number\"}},\"score\":{\"type\":\"number\"}},\"required\":[\"matched\",\"score\"],\"additionalProperties\":false},\"specifications\":{\"type\":\"object\",\"propertyNames\":{\"type\":\"string\"},\"additionalProperties\":{\"type\":\"object\",\"propertyNames\":{\"type\":\"string\"},\"additionalProperties\":{\"$ref\":\"#/$defs/schema1\"}}},\"variantCount\":{\"description\":\"Eligible variants of this product. Absent: none counted.\",\"type\":\"integer\",\"exclusiveMinimum\":0,\"maximum\":9007199254740991}},\"required\":[\"category\",\"categories\",\"productType\",\"sampleSubject\",\"colorOptionValueId\",\"hasDeclaredColor\",\"code\",\"brand\",\"name\",\"variantLabel\",\"product\",\"variantId\"],\"additionalProperties\":false}},\"nameWords\":{\"description\":\"Empty name lookup: each word, and whether a name in scope starts it. Unmatched words were left out unless all or none matched.\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"matched\":{\"type\":\"boolean\"},\"word\":{\"type\":\"string\"}},\"required\":[\"matched\",\"word\"],\"additionalProperties\":false}},\"pageInfo\":{\"type\":\"object\",\"properties\":{\"endCursor\":{\"type\":[\"string\",\"null\"]},\"hasNextPage\":{\"type\":\"boolean\"}},\"required\":[\"endCursor\",\"hasNextPage\"],\"additionalProperties\":false},\"preferenceMatchesRemain\":{\"description\":\"False: nothing from this page on meets any optionalFilter.\",\"type\":\"boolean\"},\"unavailableVariantIds\":{\"description\":\"Filtered ids in the catalog this list can't show, e.g. retired.\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"unresolvedVariantIds\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"unstated\":{\"description\":\"Filtered attributes no variant in scope states at all.\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"words\":{\"description\":\"Each word asked for, and whether any variant in scope names it.\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"matched\":{\"type\":\"boolean\"},\"word\":{\"type\":\"string\"}},\"required\":[\"matched\",\"word\"],\"additionalProperties\":false}},\"choices\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"alternatives\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"group\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"},\"kind\":{\"type\":\"string\"},\"label\":{\"type\":\"string\"}},\"required\":[\"group\",\"id\",\"kind\",\"label\"],\"additionalProperties\":false}},\"basis\":{\"type\":\"string\"},\"handle\":{\"type\":\"string\"},\"reason\":{\"type\":\"string\"},\"selected\":{\"type\":\"object\",\"properties\":{\"group\":{\"type\":\"string\"},\"id\":{\"type\":\"string\"},\"kind\":{\"type\":\"string\"},\"label\":{\"type\":\"string\"}},\"required\":[\"group\",\"id\",\"kind\",\"label\"],\"additionalProperties\":false},\"text\":{\"type\":\"string\"}},\"requ",
|
|
4
|
+
"ired\":[\"alternatives\",\"basis\",\"handle\",\"reason\",\"selected\",\"text\"],\"additionalProperties\":false}},\"colors\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"hex\":{\"type\":\"string\",\"pattern\":\"^#[\\\\da-f]{6}$\",\"description\":\"The color's own point in the region; it orders matches.\"},\"intent\":{\"type\":\"string\",\"enum\":[\"required\",\"preferred\"]},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"not_in\"]},\"range\":{\"type\":\"object\",\"properties\":{\"chroma\":{\"type\":\"array\",\"prefixItems\":[{\"type\":\"number\"},{\"type\":\"number\"}],\"items\":false,\"minItems\":2,\"maxItems\":2},\"hue\":{\"anyOf\":[{\"type\":\"array\",\"prefixItems\":[{\"type\":\"number\"},{\"type\":\"number\"}],\"items\":false,\"minItems\":2,\"maxItems\":2},{\"type\":\"null\"}]},\"lightness\":{\"type\":\"array\",\"prefixItems\":[{\"type\":\"number\"},{\"type\":\"number\"}],\"items\":false,\"minItems\":2,\"maxItems\":2}},\"required\":[\"chroma\",\"hue\",\"lightness\"],\"additionalProperties\":false}},\"required\":[\"hex\",\"op\",\"range\"],\"additionalProperties\":false},\"description\":\"The color regions that ran.\"},\"corrections\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"correction\":{\"type\":\"string\"},\"word\":{\"type\":\"string\"}},\"required\":[\"correction\",\"word\"],\"additionalProperties\":false}},\"filters\":{\"type\":\"object\",\"properties\":{\"anyField\":{\"description\":\"One of values in any of fields (term attributes).\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"fields\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"unstated\":{\"type\":\"string\",\"const\":\"pass\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"fields\",\"op\",\"values\"],\"additionalProperties\":false}},\"numbers\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"eq\",\"gt\",\"gte\",\"lt\",\"lte\"]},\"value\":{\"type\":\"number\"}},\"required\":[\"field\",\"op\",\"value\"],\"additionalProperties\":false}},\"presence\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"exists\",\"missing\"]}},\"required\":[\"field\",\"op\"],\"additionalProperties\":false}},\"terms\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"all\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"unstated\":{\"type\":\"string\",\"const\":\"pass\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"field\",\"op\",\"values\"],\"additionalProperties\":false}}},\"additionalProperties\":false,\"description\":\"The filters that ran, the scope among them.\"},\"name\":{\"type\":\"string\",\"description\":\"The paint name looked up.\"},\"oneRowPer\":{\"type\":\"string\",\"enum\":[\"product\",\"variant\",\"paint_variant_or_product\"],\"description\":\"A row per product, per variant, or per exact paint variant followed by other products.\"},\"optionalFilters\":{\"type\":\"object\",\"properties\":{\"anyField\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"fields\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"weight\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":10}},\"required\":[\"fields\",\"op\",\"values\",\"weight\"],\"additionalProperties\":false}},\"numbers\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"eq\",\"gt\",\"gte\",\"lt\",\"lte\"]},\"value\":{\"type\":\"number\"},\"weight\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":10}},\"required\":[\"field\",\"op\",\"value\",\"weight\"],\"additionalProperties\":false}},\"presence\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"exists\",\"missing\"]},\"weight\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":10}},\"required\":[\"field\",\"op\",\"weight\"],\"additionalProperties\":false}},\"terms\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"all\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"weight\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":10}},\"required\":[\"field\",\"op\",\"values\",\"weight\"],\"additionalProperties\":fal",
|
|
5
|
+
"se}}},\"additionalProperties\":false,\"description\":\"The preferences that ran.\"},\"outcome\":{\"type\":\"string\",\"enum\":[\"page\",\"partial_match\",\"no_match\",\"nothing_understood\",\"out_of_scope\",\"brand_not_in_catalog\"],\"description\":\"How the search ended.\"},\"scope\":{\"type\":\"object\",\"properties\":{\"anyField\":{\"description\":\"One of values in any of fields (term attributes).\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"fields\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"unstated\":{\"type\":\"string\",\"const\":\"pass\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"fields\",\"op\",\"values\"],\"additionalProperties\":false}},\"numbers\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"eq\",\"gt\",\"gte\",\"lt\",\"lte\"]},\"value\":{\"type\":\"number\"}},\"required\":[\"field\",\"op\",\"value\"],\"additionalProperties\":false}},\"presence\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"exists\",\"missing\"]}},\"required\":[\"field\",\"op\"],\"additionalProperties\":false}},\"terms\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"field\":{\"type\":\"string\"},\"op\":{\"type\":\"string\",\"enum\":[\"in\",\"all\",\"not_in\"]},\"orText\":{\"type\":\"string\"},\"unstated\":{\"type\":\"string\",\"const\":\"pass\"},\"values\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"field\",\"op\",\"values\"],\"additionalProperties\":false}}},\"additionalProperties\":false,\"description\":\"The fixed scope, repeated in filters.\"},\"understood\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"applied\":{\"type\":\"string\",\"enum\":[\"filter\",\"preference\",\"not_applied\"],\"description\":\"filter narrows; preference only ranks; not_applied did neither.\"},\"id\":{\"type\":\"string\",\"description\":\"The parser's condition id.\"},\"kind\":{\"type\":\"string\",\"enum\":[\"category\",\"brand\",\"term\",\"number\",\"color\",\"paint\",\"name\",\"scope\"]},\"label\":{\"type\":\"string\",\"description\":\"What the words were read as.\"},\"note\":{\"type\":\"string\"},\"text\":{\"type\":\"string\",\"description\":\"The query words it came from.\"}},\"required\":[\"applied\",\"id\",\"kind\",\"label\",\"text\"],\"additionalProperties\":false}},\"unresolved\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"items\",\"pageInfo\",\"oneRowPer\",\"outcome\",\"understood\"],\"additionalProperties\":false}}},\"path\":\"/api/v1/variants/search\",\"requiredHeaders\":[],\"requiresVisibleConfirmation\":false}]",
|
|
6
6
|
].join("");
|
|
7
7
|
export const WEBMCP_TOOLS = JSON.parse(json);
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
export type SamplizeCatalogOptions = {
|
|
2
|
-
limit?: number;
|
|
3
|
-
/** Continue with unchanged filters and sourceVersion; omit when filters change. */
|
|
4
|
-
after?: string;
|
|
5
|
-
/** Exact canonical identities, at most 100. Unknown/ineligible IDs are omitted; no substitution. Combined filters intersect. */
|
|
6
|
-
variantIds?: string[];
|
|
7
|
-
/** Pin every subsequent page to the version returned by the first page. */
|
|
8
|
-
sourceVersion?: string;
|
|
9
|
-
};
|
|
10
|
-
export type SamplizeCatalogProduct = {
|
|
11
|
-
variantId: string;
|
|
12
|
-
productId: string;
|
|
13
|
-
name: string;
|
|
14
|
-
code: string;
|
|
15
|
-
brand: {
|
|
16
|
-
slug: string;
|
|
17
|
-
name: string;
|
|
18
|
-
};
|
|
19
|
-
hex: string;
|
|
20
|
-
hexSource: {
|
|
21
|
-
publisher: string;
|
|
22
|
-
url: string | null;
|
|
23
|
-
source: "resolved_variant";
|
|
24
|
-
valueSource: string | null;
|
|
25
|
-
};
|
|
26
|
-
lrv: number | null;
|
|
27
|
-
lrvSource: SamplizeLrvObservation | null;
|
|
28
|
-
lrvObservations: SamplizeLrvObservation[];
|
|
29
|
-
/** The primary sample variant count, never an aggregate of product orders. */
|
|
30
|
-
demand: SamplizeDemand | null;
|
|
31
|
-
collectionMemberships: SamplizeCollectionMembership[];
|
|
32
|
-
colorAnalysis: Record<string, unknown>;
|
|
33
|
-
oklab: {
|
|
34
|
-
L: number;
|
|
35
|
-
a: number;
|
|
36
|
-
b: number;
|
|
37
|
-
};
|
|
38
|
-
sourceProductId: string | null;
|
|
39
|
-
url: string | null;
|
|
40
|
-
sizeVariants: {
|
|
41
|
-
sourceVariantId: string;
|
|
42
|
-
sku: string | null;
|
|
43
|
-
title: string | null;
|
|
44
|
-
price: number | null;
|
|
45
|
-
inventoryAvailable: boolean;
|
|
46
|
-
demand: SamplizeDemand | null;
|
|
47
|
-
}[];
|
|
48
|
-
publishedHexes: SamplizeHexObservation[];
|
|
49
|
-
hexObservations: SamplizeHexObservation[];
|
|
50
|
-
};
|
|
51
|
-
export type SamplizeCatalogPage = {
|
|
52
|
-
schemaVersion: 2;
|
|
53
|
-
searchCatalogSubset: "samplizeCatalog";
|
|
54
|
-
sourceVersion: string;
|
|
55
|
-
source: Record<string, unknown>;
|
|
56
|
-
/** Number of eligible records matching the supplied filters. */
|
|
57
|
-
total: number;
|
|
58
|
-
unavailableFields: string[];
|
|
59
|
-
items: SamplizeCatalogProduct[];
|
|
60
|
-
nextCursor: string | null;
|
|
61
|
-
/** True on the final page; completeness requires collecting total unique IDs. */
|
|
62
|
-
complete: boolean;
|
|
63
|
-
};
|
|
64
|
-
export type SamplizeHexObservation = {
|
|
65
|
-
hex: string;
|
|
66
|
-
publisher: string;
|
|
67
|
-
source: string;
|
|
68
|
-
sourceUrl: string | null;
|
|
69
|
-
valueSource: string;
|
|
70
|
-
observedAt: string | null;
|
|
71
|
-
differsFromSelected: boolean;
|
|
72
|
-
};
|
|
73
|
-
export type SamplizePublicationSource = {
|
|
74
|
-
publisher: "Samplize";
|
|
75
|
-
source: "algolia_shopify_products";
|
|
76
|
-
sourceUrl: string;
|
|
77
|
-
observedAt: string | null;
|
|
78
|
-
};
|
|
79
|
-
export type SamplizeLrvObservation = {
|
|
80
|
-
field: string;
|
|
81
|
-
value: number;
|
|
82
|
-
} & SamplizePublicationSource;
|
|
83
|
-
export type SamplizeDemand = {
|
|
84
|
-
field: "recently_ordered_count";
|
|
85
|
-
sourceVariantId: string;
|
|
86
|
-
defaultAttributeLevel: "shopify_variant";
|
|
87
|
-
recentlyOrderedCount: number;
|
|
88
|
-
/** The publisher does not supply the time window. */
|
|
89
|
-
window: null;
|
|
90
|
-
} & SamplizePublicationSource;
|
|
91
|
-
export type SamplizeCollectionMembership = {
|
|
92
|
-
sourceCollectionId: string;
|
|
93
|
-
handle: string;
|
|
94
|
-
url: string;
|
|
95
|
-
publisher: "Samplize";
|
|
96
|
-
source: "algolia_shopify_products";
|
|
97
|
-
observedAt: string | null;
|
|
98
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/samplize-colorvec.d.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
export declare const SAMPLIZE_COLORVEC_RANKING_VERSION = "solid-colorvec-cosine-v2";
|
|
2
|
-
export declare const SAMPLIZE_COLORVEC_EMBEDDING_VERSION = "oklch-anchor-quantiles-v12";
|
|
3
|
-
export type SamplizeColorVecPaint = {
|
|
4
|
-
variantId: string;
|
|
5
|
-
hex: string;
|
|
6
|
-
brand: string;
|
|
7
|
-
oklab: {
|
|
8
|
-
L: number;
|
|
9
|
-
a: number;
|
|
10
|
-
b: number;
|
|
11
|
-
};
|
|
12
|
-
family: string;
|
|
13
|
-
lightness: string;
|
|
14
|
-
intensity: string;
|
|
15
|
-
vector: number[] | string;
|
|
16
|
-
};
|
|
17
|
-
export type SamplizeColorVecCache = {
|
|
18
|
-
sourceVersion: string;
|
|
19
|
-
dictionaryVersion: string;
|
|
20
|
-
embeddingVersion: string;
|
|
21
|
-
rankingVersion: string;
|
|
22
|
-
generatedAt: string;
|
|
23
|
-
paints: SamplizeColorVecPaint[];
|
|
24
|
-
};
|
|
25
|
-
export type SamplizeColorVecInput = {
|
|
26
|
-
hex?: string;
|
|
27
|
-
reference?: string;
|
|
28
|
-
palette?: {
|
|
29
|
-
hex: string;
|
|
30
|
-
proportion: number;
|
|
31
|
-
}[];
|
|
32
|
-
direction?: "similar" | "lighter" | "darker" | "muted";
|
|
33
|
-
brand?: string[];
|
|
34
|
-
family?: string[];
|
|
35
|
-
lightness?: string[];
|
|
36
|
-
intensity?: string[];
|
|
37
|
-
lightnessMin?: number;
|
|
38
|
-
lightnessMax?: number;
|
|
39
|
-
temperatureMin?: number;
|
|
40
|
-
temperatureMax?: number;
|
|
41
|
-
limit?: number;
|
|
42
|
-
};
|
|
43
|
-
export declare const samplizeSolidColorVector: (hex: string) => number[];
|
|
44
|
-
/** Canonical constraints are shared by full-cache similarity and constrained text retrieval. */
|
|
45
|
-
export declare const selectSamplizeEligiblePaints: <T extends Omit<SamplizeColorVecPaint, "vector">>(paints: T[], input: SamplizeColorVecInput) => {
|
|
46
|
-
counts: Record<"brand" | "family" | "intensity" | "lightness", Record<string, number>>;
|
|
47
|
-
eligible: T[];
|
|
48
|
-
reference: T | undefined;
|
|
49
|
-
};
|
|
50
|
-
/** Official portable MG ranking over its complete versioned sampling-channel projection. */
|
|
51
|
-
export declare const createSamplizeColorVecIndex: (cache: SamplizeColorVecCache) => {
|
|
52
|
-
search(input: SamplizeColorVecInput): {
|
|
53
|
-
countBasis: "complete-catalog";
|
|
54
|
-
counts: Record<"brand" | "family" | "intensity" | "lightness", Record<string, number>>;
|
|
55
|
-
dictionaryVersion: string;
|
|
56
|
-
eligibleCount: number;
|
|
57
|
-
embeddingVersion: string;
|
|
58
|
-
groups: {
|
|
59
|
-
hex: string;
|
|
60
|
-
ids: string[];
|
|
61
|
-
proportion: number;
|
|
62
|
-
quota: number;
|
|
63
|
-
shortfall: number;
|
|
64
|
-
}[];
|
|
65
|
-
ids: string[];
|
|
66
|
-
limited: boolean;
|
|
67
|
-
rankingVersion: string;
|
|
68
|
-
sourceVersion: string;
|
|
69
|
-
};
|
|
70
|
-
};
|
package/samplize-colorvec.js
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { EMBEDDING_VERSION, EMBEDDING_VECTOR_SIZE, embeddingCosineSimilarity, paletteToEmbedding, } from "@materialinstruments/colorscope/embedding";
|
|
2
|
-
export const SAMPLIZE_COLORVEC_RANKING_VERSION = "solid-colorvec-cosine-v2";
|
|
3
|
-
export const SAMPLIZE_COLORVEC_EMBEDDING_VERSION = EMBEDDING_VERSION;
|
|
4
|
-
const decodeVector = (encoded) => {
|
|
5
|
-
const bytes = Uint8Array.from(atob(encoded), (c) => {
|
|
6
|
-
const codePoint = c.codePointAt(0);
|
|
7
|
-
if (codePoint === undefined) {
|
|
8
|
-
throw new Error("Missing encoded vector byte.");
|
|
9
|
-
}
|
|
10
|
-
return codePoint;
|
|
11
|
-
});
|
|
12
|
-
if (bytes.length !== EMBEDDING_VECTOR_SIZE * 4) {
|
|
13
|
-
throw new Error("Invalid color vector size.");
|
|
14
|
-
}
|
|
15
|
-
const view = new DataView(bytes.buffer);
|
|
16
|
-
return Array.from({ length: EMBEDDING_VECTOR_SIZE }, (_, i) => view.getFloat32(i * 4, true));
|
|
17
|
-
};
|
|
18
|
-
const facets = ["brand", "family", "lightness", "intensity"];
|
|
19
|
-
const identityOrder = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
20
|
-
export const samplizeSolidColorVector = (hex) => {
|
|
21
|
-
if (!/^#[0-9a-f]{6}$/iu.test(hex)) {
|
|
22
|
-
throw new Error("A six-digit published color is required.");
|
|
23
|
-
}
|
|
24
|
-
return paletteToEmbedding([{ hex, proportion: 1 }], { validateOklab: true });
|
|
25
|
-
};
|
|
26
|
-
const findReferencePaint = (paints, input) => {
|
|
27
|
-
const reference = input.reference !== undefined && input.reference !== ""
|
|
28
|
-
? paints.find((p) => p.variantId === input.reference)
|
|
29
|
-
: undefined;
|
|
30
|
-
if (input.reference !== undefined && input.reference !== "" && !reference) {
|
|
31
|
-
throw new Error("The reference is absent from this catalog version.");
|
|
32
|
-
}
|
|
33
|
-
return reference;
|
|
34
|
-
};
|
|
35
|
-
/** Canonical constraints are shared by full-cache similarity and constrained text retrieval. */
|
|
36
|
-
export const selectSamplizeEligiblePaints = (paints, input) => {
|
|
37
|
-
const reference = findReferencePaint(paints, input);
|
|
38
|
-
const low = input.lightnessMin ?? 0;
|
|
39
|
-
const high = input.lightnessMax ?? 1;
|
|
40
|
-
const cool = input.temperatureMin ?? -0.4;
|
|
41
|
-
const warm = input.temperatureMax ?? 0.4;
|
|
42
|
-
if (![low, high, cool, warm].every(Number.isFinite) ||
|
|
43
|
-
low > high ||
|
|
44
|
-
cool > warm) {
|
|
45
|
-
throw new Error("Appearance ranges must be finite and ordered.");
|
|
46
|
-
}
|
|
47
|
-
const candidates = paints.filter((p) => {
|
|
48
|
-
if (!reference) {
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
if (p.variantId === reference.variantId) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
if (input.direction === "lighter") {
|
|
55
|
-
return p.oklab.L > reference.oklab.L;
|
|
56
|
-
}
|
|
57
|
-
if (input.direction === "darker") {
|
|
58
|
-
return p.oklab.L < reference.oklab.L;
|
|
59
|
-
}
|
|
60
|
-
if (input.direction === "muted") {
|
|
61
|
-
return (Math.hypot(p.oklab.a, p.oklab.b) <
|
|
62
|
-
Math.hypot(reference.oklab.a, reference.oklab.b));
|
|
63
|
-
}
|
|
64
|
-
return true;
|
|
65
|
-
});
|
|
66
|
-
const matches = (p, omit) => p.oklab.L >= low &&
|
|
67
|
-
p.oklab.L <= high &&
|
|
68
|
-
p.oklab.b >= cool &&
|
|
69
|
-
p.oklab.b <= warm &&
|
|
70
|
-
facets.every((f) => f === omit ||
|
|
71
|
-
input[f] === undefined ||
|
|
72
|
-
input[f].length === 0 ||
|
|
73
|
-
input[f].includes(p[f]));
|
|
74
|
-
const counts = {
|
|
75
|
-
brand: {},
|
|
76
|
-
family: {},
|
|
77
|
-
intensity: {},
|
|
78
|
-
lightness: {},
|
|
79
|
-
};
|
|
80
|
-
for (const p of candidates) {
|
|
81
|
-
for (const f of facets) {
|
|
82
|
-
if (matches(p, f)) {
|
|
83
|
-
counts[f][p[f]] = (counts[f][p[f]] ?? 0) + 1;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
const eligible = candidates.filter((p) => matches(p));
|
|
88
|
-
return { counts, eligible, reference };
|
|
89
|
-
};
|
|
90
|
-
const searchPalette = (input, reference) => {
|
|
91
|
-
const palette = (input.palette !== undefined && input.palette.length > 0
|
|
92
|
-
? input.palette
|
|
93
|
-
: [{ hex: input.hex ?? reference?.hex ?? "", proportion: 1 }])
|
|
94
|
-
.map((p) => ({ ...p, hex: p.hex.toLowerCase() }))
|
|
95
|
-
.toSorted((a, b) => b.proportion - a.proportion || identityOrder(a.hex, b.hex));
|
|
96
|
-
if (palette.length > 12 ||
|
|
97
|
-
palette.some((p) => !Number.isFinite(p.proportion) || p.proportion <= 0 || p.proportion > 1)) {
|
|
98
|
-
throw new Error("Supply up to twelve positive image color shares.");
|
|
99
|
-
}
|
|
100
|
-
return palette;
|
|
101
|
-
};
|
|
102
|
-
const searchSamplizePaints = (cache, paints, input, vectorFor) => {
|
|
103
|
-
const limit = input.limit ?? 48;
|
|
104
|
-
if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
|
|
105
|
-
throw new Error("Choose between 1 and 100 suggestions.");
|
|
106
|
-
}
|
|
107
|
-
const { reference, eligible, counts } = selectSamplizeEligiblePaints(paints, input);
|
|
108
|
-
const palette = searchPalette(input, reference);
|
|
109
|
-
const total = palette.reduce((sum, p) => sum + p.proportion, 0);
|
|
110
|
-
const buckets = palette.map((p, position) => {
|
|
111
|
-
const bucketPaints = [];
|
|
112
|
-
return {
|
|
113
|
-
...p,
|
|
114
|
-
paints: bucketPaints,
|
|
115
|
-
position,
|
|
116
|
-
quota: Math.floor((limit * p.proportion) / total),
|
|
117
|
-
remainder: ((limit * p.proportion) / total) % 1,
|
|
118
|
-
vector: vectorFor(p.hex),
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
let remaining = limit - buckets.reduce((sum, p) => sum + p.quota, 0);
|
|
122
|
-
for (const p of [...buckets].toSorted((a, b) => b.remainder - a.remainder || a.position - b.position)) {
|
|
123
|
-
if (remaining-- > 0) {
|
|
124
|
-
p.quota++;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
for (const paint of eligible) {
|
|
128
|
-
let best = buckets[0];
|
|
129
|
-
if (best === undefined) {
|
|
130
|
-
throw new Error("Missing first palette bucket.");
|
|
131
|
-
}
|
|
132
|
-
let score = embeddingCosineSimilarity(paint.vector, best.vector);
|
|
133
|
-
for (let i = 1; i < buckets.length; i++) {
|
|
134
|
-
const candidate = buckets[i];
|
|
135
|
-
if (candidate === undefined) {
|
|
136
|
-
throw new Error("Missing palette bucket.");
|
|
137
|
-
}
|
|
138
|
-
const next = embeddingCosineSimilarity(paint.vector, candidate.vector);
|
|
139
|
-
if (next > score) {
|
|
140
|
-
best = candidate;
|
|
141
|
-
score = next;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
best.paints.push({ id: paint.variantId, score });
|
|
145
|
-
}
|
|
146
|
-
const groups = buckets
|
|
147
|
-
.toSorted((a, b) => b.proportion - a.proportion || a.position - b.position)
|
|
148
|
-
.map((p) => {
|
|
149
|
-
const ids = p.paints
|
|
150
|
-
.toSorted((a, b) => b.score - a.score || identityOrder(a.id, b.id))
|
|
151
|
-
.slice(0, p.quota)
|
|
152
|
-
.map((paint) => paint.id);
|
|
153
|
-
return {
|
|
154
|
-
hex: p.hex,
|
|
155
|
-
ids,
|
|
156
|
-
proportion: p.proportion,
|
|
157
|
-
quota: p.quota,
|
|
158
|
-
shortfall: p.quota - ids.length,
|
|
159
|
-
};
|
|
160
|
-
});
|
|
161
|
-
const ids = groups.flatMap((p) => p.ids);
|
|
162
|
-
return {
|
|
163
|
-
countBasis: "complete-catalog",
|
|
164
|
-
counts,
|
|
165
|
-
dictionaryVersion: cache.dictionaryVersion,
|
|
166
|
-
eligibleCount: eligible.length,
|
|
167
|
-
embeddingVersion: cache.embeddingVersion,
|
|
168
|
-
groups,
|
|
169
|
-
ids,
|
|
170
|
-
limited: eligible.length > ids.length,
|
|
171
|
-
rankingVersion: cache.rankingVersion,
|
|
172
|
-
sourceVersion: cache.sourceVersion,
|
|
173
|
-
};
|
|
174
|
-
};
|
|
175
|
-
/** Official portable MG ranking over its complete versioned sampling-channel projection. */
|
|
176
|
-
export const createSamplizeColorVecIndex = (cache) => {
|
|
177
|
-
if (cache.embeddingVersion !== EMBEDDING_VERSION ||
|
|
178
|
-
cache.rankingVersion !== SAMPLIZE_COLORVEC_RANKING_VERSION) {
|
|
179
|
-
throw new Error("The color cache uses an incompatible embedding or ranking version. Refresh it before searching.");
|
|
180
|
-
}
|
|
181
|
-
if (!cache.sourceVersion ||
|
|
182
|
-
!cache.dictionaryVersion ||
|
|
183
|
-
!Number.isFinite(Date.parse(cache.generatedAt))) {
|
|
184
|
-
throw new Error("The color cache is missing its provenance.");
|
|
185
|
-
}
|
|
186
|
-
const paints = cache.paints.map((p) => ({
|
|
187
|
-
...p,
|
|
188
|
-
vector: typeof p.vector === "string" ? decodeVector(p.vector) : p.vector,
|
|
189
|
-
}));
|
|
190
|
-
const identities = new Set();
|
|
191
|
-
for (const paint of paints) {
|
|
192
|
-
if (identities.has(paint.variantId) ||
|
|
193
|
-
paint.vector.length !== EMBEDDING_VECTOR_SIZE ||
|
|
194
|
-
!paint.vector.every(Number.isFinite) ||
|
|
195
|
-
![paint.oklab.L, paint.oklab.a, paint.oklab.b].every(Number.isFinite)) {
|
|
196
|
-
throw new Error("The color cache contains invalid or duplicate paint records.");
|
|
197
|
-
}
|
|
198
|
-
identities.add(paint.variantId);
|
|
199
|
-
}
|
|
200
|
-
const vectors = new Map();
|
|
201
|
-
const vectorFor = (hex) => {
|
|
202
|
-
const key = hex.toLowerCase();
|
|
203
|
-
let value = vectors.get(key);
|
|
204
|
-
if (!value) {
|
|
205
|
-
value = samplizeSolidColorVector(hex);
|
|
206
|
-
if (vectors.size >= 512) {
|
|
207
|
-
const oldest = vectors.keys().next().value;
|
|
208
|
-
if (oldest === undefined) {
|
|
209
|
-
throw new Error("Missing oldest cached color vector.");
|
|
210
|
-
}
|
|
211
|
-
vectors.delete(oldest);
|
|
212
|
-
}
|
|
213
|
-
vectors.set(key, value);
|
|
214
|
-
}
|
|
215
|
-
return value;
|
|
216
|
-
};
|
|
217
|
-
return {
|
|
218
|
-
search(input) {
|
|
219
|
-
return searchSamplizePaints(cache, paints, input, vectorFor);
|
|
220
|
-
},
|
|
221
|
-
};
|
|
222
|
-
};
|