@instruments/materialgraph 0.19.0 → 0.21.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.
@@ -57,6 +57,33 @@ export interface AvailableSubstitutesResponse {
57
57
  items: SubstituteResultItem[];
58
58
  candidatePoolSize: number;
59
59
  droppedUnavailable: number;
60
+ /**
61
+ * MG-1686, MG-1783. True when the candidate read hit the bounded pool ceiling,
62
+ * so more materials match the signature than were ranked. A cut pool is an
63
+ * even SAMPLE across the id keyspace rather than its lowest window, so the
64
+ * ranked set is representative of the match set without being all of it —
65
+ * treat the items as the best of a sample, never as the best that exist. A cut
66
+ * pool that produced NO items answers `inconclusive` instead, so `available`
67
+ * with an empty `items` always means a complete search that found nothing.
68
+ */
69
+ poolTruncated: boolean;
70
+ supersededBy: MaterialSuccessor | null;
71
+ nextCursor?: string;
72
+ }
73
+ /**
74
+ * MG-1686. The search read a bounded window of the matches and nothing in it
75
+ * reached the page, while more matches existed past the window. It is not an
76
+ * answer of "nothing can replace this" — that answer is `available` with an
77
+ * empty `items`. `reason` names what happened and the next move; follow
78
+ * `nextCursor` when it is present.
79
+ */
80
+ export interface InconclusiveSubstitutesResponse {
81
+ status: "inconclusive";
82
+ signatureUsed: AvailableSubstituteSignature;
83
+ items: [];
84
+ candidatePoolSize: number;
85
+ droppedUnavailable: number;
86
+ reason: string;
60
87
  supersededBy: MaterialSuccessor | null;
61
88
  nextCursor?: string;
62
89
  }
@@ -72,4 +99,4 @@ export interface InsufficientSubstitutesResponse {
72
99
  items: [];
73
100
  supersededBy: MaterialSuccessor | null;
74
101
  }
75
- export type FindSubstitutesResponse = AvailableSubstitutesResponse | UnsupportedSubstitutesResponse | InsufficientSubstitutesResponse;
102
+ export type FindSubstitutesResponse = AvailableSubstitutesResponse | InconclusiveSubstitutesResponse | UnsupportedSubstitutesResponse | InsufficientSubstitutesResponse;
package/types.d.ts CHANGED
@@ -1,7 +1,8 @@
1
+ export type { SearchResponse } from "./search-response-types.js";
2
+ import type { ResponseAttribution } from "./attribution-types.js";
1
3
  import type { BySpecVerdict } from "./by-spec-types.js";
2
4
  /**
3
5
  * Hand-mirrored wire types for the MaterialGraph public API (spec 0.5.0).
4
- *
5
6
  * These interfaces intentionally have NO runtime dependency on any
6
7
  * `@materialgraph/*` package — they are a standalone, publishable mirror of the
7
8
  * shapes in `apps/web/public/openapi.yaml` and the captured fixtures under
@@ -31,6 +32,7 @@ import type { Cursor, ProductId, VariantId } from "./identifiers.js";
31
32
  import type { MaterialDetail, MaterialTile } from "./material-types.js";
32
33
  import type { QueryUnderstanding } from "./query-understanding-types.js";
33
34
  import type { CollapsedVariant, SearchAnatomyMember } from "./search-collapse-types.js";
35
+ import type { MoodInterpretation } from "./search-mood-types.js";
34
36
  import type { SearchDisambiguation, SearchSuggestion } from "./search-refinement-types.js";
35
37
  import type { CompoundColourConstraintReceipt, CompoundFormConstraintReceipt, SearchExecutionPlan, SearchMode, SearchRefinementReceipt, SearchRerankReport, SearchResponseExplainReceipts } from "./search-response-receipt-types.js";
36
38
  import type { SearchWindowReceipt } from "./search-window-types.js";
@@ -114,6 +116,8 @@ export interface VisualMeaning {
114
116
  * `visualMeanings` is not "this material has no visual meaning".
115
117
  */
116
118
  export interface SearchResultItem {
119
+ /** This hit's attribution key — see {@link ResponseAttribution}. Opaque. */
120
+ resultId?: string;
117
121
  /** Accepted sampleability fact. Absent means unknown, never false. */
118
122
  sampleable?: boolean;
119
123
  /** Opaque — round-trip verbatim into `material()`, `pairings()`, `similarTo`. */
@@ -263,42 +267,6 @@ export interface SearchResultItem {
263
267
  */
264
268
  attributes?: Record<string, string | string[] | null>;
265
269
  }
266
- /**
267
- * The lean `view:"card"` result item — identity + name + thumbnail + score.
268
- *
269
- * A PROJECTION, not a smaller answer: a field the card omits (palette, verdict,
270
- * signals, availability) is unread here, never known-absent. Re-read the same
271
- * `variantId` at `view: "full"` or via `material()` before claiming anything the
272
- * card does not carry.
273
- */
274
- export interface SearchCardItem {
275
- /** Accepted sampleability fact. Absent means unknown, never false. */
276
- sampleable?: boolean;
277
- /** Opaque — round-trip verbatim. */
278
- variantId: VariantId;
279
- productId: ProductId | null;
280
- brandSlug: string | null;
281
- brand: string;
282
- /** Product name (the full item's `product`). */
283
- name: string;
284
- variantName: string | null;
285
- imageUrl: string | null;
286
- projectSaveCapability?: "allowed";
287
- sourceStatus?: "provisional";
288
- score: number;
289
- /**
290
- * Resolved values for the attribute ids sent in `returnAttributes`, keyed by
291
- * attribute id. ABSENT entirely when `returnAttributes` was not sent.
292
- *
293
- * Three states, all different, and reading them as two is the mistake this
294
- * shape exists to prevent: no `attributes` key means you did not ask; a key
295
- * whose value is `null` means this material carries no accepted value for that
296
- * attribute; anything else is what the graph holds. Values resolve with the
297
- * normal variant-over-product precedence, and an array is a multi-valued
298
- * attribute rather than a list of candidates.
299
- */
300
- attributes?: Record<string, string | string[] | null>;
301
- }
302
270
  /**
303
271
  * A feed total with its honesty basis — THE CLAIM ABOUT THE MATCH SET, which is
304
272
  * a different number from `results.length` (this page).
@@ -390,12 +358,30 @@ export interface SearchFacets {
390
358
  * you asked for it. Follow `cursor` for the rest. "I found 24 materials" is
391
359
  * wrong whenever `limit` was 24.
392
360
  */
393
- export interface SearchResponse extends SearchResponseExplainReceipts {
361
+ export interface SearchData extends SearchResponseExplainReceipts {
362
+ /** Result attribution — see {@link ResponseAttribution}. `basis` is `mode` verbatim here. */
363
+ attribution?: ResponseAttribution;
394
364
  view: OpenEnum<"full" | "card">;
395
365
  /** THIS PAGE. Its length is a page size, never a total. */
396
366
  results: SearchResultItem[];
397
367
  suggestions: SearchSuggestion[];
398
368
  mode: SearchMode;
369
+ /**
370
+ * Which dense text lane answered, when one did (MG-1796). `image-text` — the
371
+ * query carried evidence it describes appearance, so it was ranked against
372
+ * image vectors; `variant-text` — ranked against each variant's written
373
+ * portrait.
374
+ *
375
+ * ABSENT means the answer did not come from the dense text arm at all: `mode`
376
+ * was never `text`, or the text arm resolved without a lane. Absence is
377
+ * UNKNOWN and never a default of `image-text` — treating it as one asserts a
378
+ * dense reading of a lexical, colour or browse answer. Absent too from any
379
+ * response produced by a server predating MG-1793.
380
+ *
381
+ * An {@link OpenEnum} because the lane vocabulary can grow: a value you do
382
+ * not recognise is a lane this client predates, not a malformed response.
383
+ */
384
+ textLane?: OpenEnum<"image-text" | "variant-text">;
399
385
  maxScore: number;
400
386
  cursor?: Cursor;
401
387
  window?: SearchWindowReceipt;
@@ -432,7 +418,7 @@ export interface SearchResponse extends SearchResponseExplainReceipts {
432
418
  * Explicit standard-search mood reading; null ids mean no selected mood.
433
419
  * Absent when mood was not evaluated or an older server produced the result.
434
420
  */
435
- moodInterpretation?: import("./search-mood-types.js").MoodInterpretation;
421
+ moodInterpretation?: MoodInterpretation;
436
422
  /**
437
423
  * Present when the query had multiple defensible readings. Says which one
438
424
  * ran, or leaves every reading non-default when the engine chose none. Every
@@ -453,11 +439,6 @@ export interface SearchResponse extends SearchResponseExplainReceipts {
453
439
  /** A `getVariantBrief` echo of the seed variant, present only in `variantId` seed mode. */
454
440
  seed?: MaterialTile | Record<string, unknown>;
455
441
  }
456
- /** The `view:"card"` response form — the lean grid projection of {@link SearchResponse}. */
457
- export interface SearchCardResponse extends Omit<SearchResponse, "view" | "results"> {
458
- view: OpenEnum<"card">;
459
- results: SearchCardItem[];
460
- }
461
442
  export type ColourDictionaryId = OpenEnum<"colour_family" | "colour_mood" | "colour_undertone">;
462
443
  export interface ColourFacetTerm {
463
444
  id: string;
@@ -606,6 +587,13 @@ export interface PairingsResponse {
606
587
  * check it before presenting the rail as demand evidence.
607
588
  */
608
589
  cospecCount: number;
590
+ /**
591
+ * Candidates dropped at hydration for violating the material contract
592
+ * (MG-985). Present ONLY when > 0. A non-zero count means the rail is
593
+ * shorter than the evidence behind it — read it before calling the rail
594
+ * complete.
595
+ */
596
+ skippedCandidates?: number;
609
597
  /** Present only when `order` was requested. Evidence tiers remain independent. */
610
598
  ordering?: PairingOrdering;
611
599
  /** Opaque continuation bound to the seed, filters, corpus, and order. */
package/webmcp.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /** Canonical operation contracts. Consumers validate both boundaries and supply their own transport. */
2
+ export interface WebMcpToolContract {
3
+ readonly name: "identify" | "search" | "compare" | "create_correction";
4
+ readonly operationId: string;
5
+ readonly path: string;
6
+ readonly method: "POST";
7
+ readonly description: string;
8
+ readonly inputSchema: Readonly<Record<string, unknown>>;
9
+ readonly outputSchema: Readonly<Record<string, unknown>>;
10
+ readonly annotations: {
11
+ readonly readOnlyHint: boolean;
12
+ readonly untrustedContentHint: boolean;
13
+ };
14
+ readonly requiresVisibleConfirmation: boolean;
15
+ readonly requiredHeaders: readonly string[];
16
+ }
17
+ export { WEBMCP_TOOLS } from "./webmcp.generated.js";
@@ -0,0 +1,2 @@
1
+ import type { WebMcpToolContract } from "./webmcp.js";
2
+ export declare const WEBMCP_TOOLS: readonly WebMcpToolContract[];