@instruments/materialgraph 0.7.0 → 0.8.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/runs.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { HttpTransport } from "./http-transport.js";
2
2
  import type { FinishScheduleResponse, GetRunScheduleOptions } from "./schedule-types.js";
3
- import { type CapabilityManifestResponse, type CreatePublicRunRequest, type CreatePublicRunResponse, type DrainRunEventsOptions, type PublicRunResponse, type ResumeRunOptions, type RunEvent, type SourceMaterialBatchDetail, type SourceMaterialBatchReceipt, type StreamRunEventsOptions, type UploadSourceMaterialInput } from "./run-types.js";
3
+ import { type CapabilityManifestResponse, type CreatePublicRunRequest, type CreatePublicRunResponse, type DrainRunEventsOptions, type ListRunsOptions, type PublicRunListResponse, type PublicRunResponse, type ResumeRunOptions, type RunEvent, type SourceMaterialBatchDetail, type SourceMaterialBatchReceipt, type StreamRunEventsOptions, type UploadSourceMaterialInput } from "./run-types.js";
4
4
  /**
5
5
  * Upload one atomic source-material batch (`POST /api/v1/source-material`).
6
6
  * Accepts the pile-of-files shape (`{ files }` → repeatable `files` field) or
@@ -25,6 +25,20 @@ export declare function getSourceMaterialBatch(transport: HttpTransport, batchId
25
25
  export declare function capabilities(transport: HttpTransport, signal?: AbortSignal): Promise<CapabilityManifestResponse>;
26
26
  /** Start an asynchronous capability Run (`POST /api/v1/runs`). */
27
27
  export declare function createRun(transport: HttpTransport, body: CreatePublicRunRequest, signal?: AbortSignal): Promise<CreatePublicRunResponse>;
28
+ /**
29
+ * List your own Runs, newest first (`GET /api/v1/runs`).
30
+ *
31
+ * The recovery path for a client that still holds its API key but has lost a Run
32
+ * id — a reinstalled app, or a crash before the id from {@link createRun} was
33
+ * persisted. `{ status: "suspended" }` finds the Run still waiting on an answer.
34
+ *
35
+ * Only the calling principal's own Runs are ever returned; there is no
36
+ * cross-principal listing.
37
+ *
38
+ * Page by following `nextCursor` until it is ABSENT — a full page is not the
39
+ * signal to stop, and an absent cursor is the only one.
40
+ */
41
+ export declare function listRuns(transport: HttpTransport, options?: ListRunsOptions): Promise<PublicRunListResponse>;
28
42
  /** Get a Run's current state (`GET /api/v1/runs/{runId}`). */
29
43
  export declare function getRun(transport: HttpTransport, runId: string, signal?: AbortSignal): Promise<PublicRunResponse>;
30
44
  /**
package/runs.js CHANGED
@@ -99,6 +99,30 @@ export function createRun(transport, body, signal) {
99
99
  signal,
100
100
  });
101
101
  }
102
+ /**
103
+ * List your own Runs, newest first (`GET /api/v1/runs`).
104
+ *
105
+ * The recovery path for a client that still holds its API key but has lost a Run
106
+ * id — a reinstalled app, or a crash before the id from {@link createRun} was
107
+ * persisted. `{ status: "suspended" }` finds the Run still waiting on an answer.
108
+ *
109
+ * Only the calling principal's own Runs are ever returned; there is no
110
+ * cross-principal listing.
111
+ *
112
+ * Page by following `nextCursor` until it is ABSENT — a full page is not the
113
+ * signal to stop, and an absent cursor is the only one.
114
+ */
115
+ export function listRuns(transport, options = {}) {
116
+ const query = {
117
+ ...(options.status === undefined ? {} : { status: options.status }),
118
+ ...(options.limit === undefined ? {} : { limit: options.limit }),
119
+ ...(options.cursor === undefined ? {} : { cursor: options.cursor }),
120
+ };
121
+ return transport.requestJson(runOperation("list_public_runs"), {
122
+ ...(Object.keys(query).length > 0 ? { query } : {}),
123
+ ...(options.signal ? { signal: options.signal } : {}),
124
+ });
125
+ }
102
126
  /** Get a Run's current state (`GET /api/v1/runs/{runId}`). */
103
127
  export function getRun(transport, runId, signal) {
104
128
  return transport.requestJson(runOperation("get_public_run"), {
@@ -1,20 +1,23 @@
1
- /**
2
- * Wire types for the governed STATIC schema (`GET /api/v1/schema/*`).
3
- *
4
- * THE LENS: "what does the registry DEFINE?" — blocks, attributes, units, value
5
- * dictionaries, product types and their external mappings. Definitions, not
6
- * data: nothing here says how many materials carry an attribute or which values
7
- * the corpus holds. For that, use `mg.specificationFacets()` and
8
- * `mg.attributeValues()`; for one term explained in prose, `mg.glossary()`; for
9
- * what one material has been determined on, `mg.materialBlocks()`.
10
- *
11
- * Every id here (`attributeId`, `blockId`, product-type keys) is canonical
12
- * VOCABULARY, not an opaque token — this is where you discover it rather than
13
- * invent it.
14
- */
15
1
  import type { OpenEnum } from "./types.js";
16
2
  /** The nine governed static resources. */
17
3
  export type SchemaResource = "blocks" | "attributes" | "verticals" | "productTypes" | "units" | "valueDictionaries" | "sourceRequirements" | "productTypeTemplates" | "mappings";
4
+ /**
5
+ * Resource → the operation that serves it. Internal to the SDK (`index.ts`
6
+ * re-exports this module's TYPES only), and it lives beside
7
+ * {@link SchemaResource} rather than in the client so the mapping and the union
8
+ * it must cover cannot drift apart.
9
+ */
10
+ export declare const SCHEMA_RESOURCE_OPERATION_IDS: {
11
+ readonly blocks: "list_schema_blocks";
12
+ readonly attributes: "list_schema_attributes";
13
+ readonly verticals: "list_schema_verticals";
14
+ readonly productTypes: "list_schema_product_types";
15
+ readonly units: "list_schema_units";
16
+ readonly valueDictionaries: "list_schema_value_dictionaries";
17
+ readonly sourceRequirements: "list_schema_source_requirements";
18
+ readonly productTypeTemplates: "list_schema_product_type_templates";
19
+ readonly mappings: "list_schema_mappings";
20
+ };
18
21
  export type SchemaResourceRequest = SchemaResource;
19
22
  export interface SchemaLifecycle {
20
23
  status: OpenEnum<"draft" | "active" | "deprecated">;
@@ -1 +1,17 @@
1
- export {};
1
+ /**
2
+ * Resource → the operation that serves it. Internal to the SDK (`index.ts`
3
+ * re-exports this module's TYPES only), and it lives beside
4
+ * {@link SchemaResource} rather than in the client so the mapping and the union
5
+ * it must cover cannot drift apart.
6
+ */
7
+ export const SCHEMA_RESOURCE_OPERATION_IDS = {
8
+ blocks: "list_schema_blocks",
9
+ attributes: "list_schema_attributes",
10
+ verticals: "list_schema_verticals",
11
+ productTypes: "list_schema_product_types",
12
+ units: "list_schema_units",
13
+ valueDictionaries: "list_schema_value_dictionaries",
14
+ sourceRequirements: "list_schema_source_requirements",
15
+ productTypeTemplates: "list_schema_product_type_templates",
16
+ mappings: "list_schema_mappings",
17
+ };
@@ -143,6 +143,9 @@ export function checkSearchResultItem(value, what, fail) {
143
143
  requireString(record.product, `${what}.product`, fail);
144
144
  requireNullableString(record.brandSlug, `${what}.brandSlug`, fail);
145
145
  requireNullableString(record.productId, `${what}.productId`, fail);
146
+ // `z.string().optional()` — absent, or a string. NOT nullable: the emit path
147
+ // omits the key rather than sending null when no MB identity is known.
148
+ requireOptionalString(record.materialBankId, `${what}.materialBankId`, fail);
146
149
  requireNullableString(record.color, `${what}.color`, fail);
147
150
  requireNullableString(record.variantName, `${what}.variantName`, fail);
148
151
  requireNullableString(record.imageUrl, `${what}.imageUrl`, fail);
package/types.d.ts CHANGED
@@ -25,6 +25,7 @@
25
25
  * match set. Follow the cursor for the rest, and never report a page size as
26
26
  * a total.
27
27
  */
28
+ import type { ByColourSwatch } from "./by-colour-types.js";
28
29
  import type { BySpecVerdict } from "./by-spec-types.js";
29
30
  import type { Cursor, ProductId, VariantId } from "./identifiers.js";
30
31
  import type { MaterialDetail, MaterialTile } from "./material-types.js";
@@ -39,12 +40,22 @@ export type OpenEnum<T extends string> = T | (string & {});
39
40
  export type JsonValue = string | number | boolean | null | JsonValue[] | {
40
41
  [key: string]: JsonValue;
41
42
  };
42
- /** One palette swatch of a material's main image. */
43
+ /**
44
+ * One palette swatch of a material's main image — colour DERIVED FROM PRODUCT
45
+ * IMAGERY, so read it as visual likeness, never as a declared colour spec.
46
+ */
43
47
  export interface PaletteSwatch {
44
48
  hex: string;
45
49
  proportion: number;
46
50
  /** Stored human colour name for the swatch, when one was extracted. */
47
51
  name?: string | null;
52
+ /**
53
+ * `hex` in OKLab, derived server-side so you can sort or measure swatches
54
+ * without converting them yourself. Additive, so optional: the colour lane and
55
+ * the material record carry it, other surfaces may not, and absent means "not
56
+ * derived here" — never "achromatic".
57
+ */
58
+ oklab?: OklabTriple;
48
59
  }
49
60
  /** Loose colour metadata for a search result's main image; every field is independently optional. */
50
61
  export interface ColourMeta {
@@ -109,6 +120,16 @@ export interface SearchResultItem {
109
120
  product: string;
110
121
  brandSlug: string | null;
111
122
  productId: ProductId | null;
123
+ /**
124
+ * The variant's Material Bank SKU — the same `materialBankId` the material
125
+ * record carries, so a match card can render straight from a result instead of
126
+ * paying a per-result lookup. Populated on the MATCH lanes (`match()` and
127
+ * `matchStream()` frames).
128
+ *
129
+ * ABSENT means no MB identity is known for the variant — never that the SKU
130
+ * cannot be ordered. Presence is the orderability tell; absence is silence.
131
+ */
132
+ materialBankId?: string;
112
133
  color: string | null;
113
134
  variantName: string | null;
114
135
  imageUrl: string | null;
@@ -248,44 +269,6 @@ export interface MatchResponse {
248
269
  droppedAsDuplicateProduct: number;
249
270
  note?: string;
250
271
  }
251
- /** Coarse group + fine type of a colour match's primary product type. */
252
- export interface MatchCategory {
253
- group: string | null;
254
- type: string | null;
255
- }
256
- /**
257
- * One colour-palette match.
258
- *
259
- * `hex`, `distance` and `closeness` are OKLab geometry over colour EXTRACTED
260
- * FROM PRODUCT IMAGERY, not declared by the manufacturer. Report it as visual
261
- * likeness ("reads close to this colour"), never as a stated colour
262
- * specification.
263
- */
264
- export interface ByColourMatch {
265
- /** Opaque — round-trip verbatim. */
266
- variantId: VariantId;
267
- brand: string;
268
- product: string;
269
- color: string | null;
270
- variantName: string | null;
271
- imageUrl: string | null;
272
- hex: string | null;
273
- distance: number;
274
- closeness: number;
275
- category: MatchCategory | null;
276
- oklab: OklabTriple | null;
277
- }
278
- /** The `search/colours` response. */
279
- export interface ByColourResponse {
280
- query: {
281
- colours: string[];
282
- categories?: string[];
283
- oklab?: OklabTriple;
284
- };
285
- /** `matches.length` — THIS PAGE. Not a corpus total; this surface states none. */
286
- count: number;
287
- matches: ByColourMatch[];
288
- }
289
272
  /** One item from the pure colour-scalar browse. */
290
273
  export interface BrowseResultItem {
291
274
  /** Opaque — round-trip verbatim. */
@@ -303,6 +286,17 @@ export interface BrowseResultItem {
303
286
  vibrancy: number | null;
304
287
  };
305
288
  retired?: boolean;
289
+ /**
290
+ * The row's own image palette — the FULL stored palette of the SAME image
291
+ * `imageUrl` serves, uncapped and in stored order, each swatch with `oklab`
292
+ * (see {@link ByColourSwatch}), so a card can render, sort or group colours
293
+ * without a second call. A one-swatch palette means the extractor found one
294
+ * colour (solid-colour materials are genuinely monochrome), not that the list
295
+ * was trimmed. ABSENT when no palette is on record for that image: absent
296
+ * means unknown, NOT that the material has no colours. These swatches come
297
+ * from product imagery, not from the manufacturer.
298
+ */
299
+ palette?: ByColourSwatch[];
306
300
  }
307
301
  /**
308
302
  * A single page of the colour browse — the SDK's one genuinely cursor-paginated
@@ -508,6 +502,7 @@ export interface ResolveAttributeResponse {
508
502
  candidates: AttributeCandidate[];
509
503
  }
510
504
  export type * from "./catalog-discovery-types.js";
505
+ export type * from "./resolve-types.js";
511
506
  export type * from "./suggest-types.js";
512
507
  export type * from "./by-spec-types.js";
513
508
  export interface WhoamiResponse {
@@ -626,20 +621,6 @@ export interface SearchGetParams {
626
621
  /** Result projection — `"full"` (default) or the lean `"card"` grid form. */
627
622
  view?: OpenEnum<"full" | "card">;
628
623
  }
629
- /** Params for `search/colours`. */
630
- export interface ByColourParams {
631
- /** A single hex (with or without `#`). */
632
- hex?: string;
633
- /** A palette — repeated as one `colour` query entry each. */
634
- colour?: string | string[];
635
- /** OKLab triple (all-or-none). */
636
- l?: number;
637
- a?: number;
638
- b?: number;
639
- /** HARD category filter — display names or taxonomy ids (repeatable). */
640
- category?: string | string[];
641
- limit?: number;
642
- }
643
624
  /** Params for the pure colour `search/browse` surface. */
644
625
  export interface BrowseParams {
645
626
  sort: OpenEnum<"light" | "dark" | "vivid" | "muted" | "colourful">;
@@ -650,7 +631,13 @@ export interface BrowseParams {
650
631
  cursor?: Cursor;
651
632
  /** Page size. */
652
633
  limit?: number;
653
- /** Comma-separated product-type ids to restrict the browse to. */
634
+ /**
635
+ * Comma-separated taxonomy keys to restrict the browse to, at EITHER tier of
636
+ * `/api/v1/taxonomy/categories`. A GROUP key (`tile_surfaces`) expands to
637
+ * every product type under it, a TYPE key (`ceramic_porcelain_tile`) stands
638
+ * for itself, and a mixed list is their deduplicated union. A key in neither
639
+ * tier is a 400 listing the valid keys — never an empty page.
640
+ */
654
641
  types?: string;
655
642
  }
656
643
  /** The Material Match request body — exactly one of `imageBase64`, `imageUrl`, `vector`. */
@@ -695,6 +682,7 @@ export interface MaterialsBatchOptions {
695
682
  export interface PairingsOptions {
696
683
  /** Comma-separated coarse category display names; filters both arms. */
697
684
  categories?: string;
685
+ /** Page size, 1–24 inclusive (default 12). The server rejects (400), not clamps, values outside this range. */
698
686
  limit?: number;
699
687
  /** Graph-owned order applied within fixed cospec → considered → colour tiers. */
700
688
  order?: PairingOrderMode;