@commerce-ai-tool/core 2.4.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 (118) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +11 -0
  4. package/dist/ai/factory.d.ts +5 -0
  5. package/dist/ai/factory.d.ts.map +1 -0
  6. package/dist/ai/index.d.ts +3 -0
  7. package/dist/ai/index.d.ts.map +1 -0
  8. package/dist/ai/json-schema-errors.d.ts +4 -0
  9. package/dist/ai/json-schema-errors.d.ts.map +1 -0
  10. package/dist/ai/providers/bedrock.d.ts +19 -0
  11. package/dist/ai/providers/bedrock.d.ts.map +1 -0
  12. package/dist/ai/providers/openrouter.d.ts +27 -0
  13. package/dist/ai/providers/openrouter.d.ts.map +1 -0
  14. package/dist/ai/types.d.ts +23 -0
  15. package/dist/ai/types.d.ts.map +1 -0
  16. package/dist/cache/search-cache.d.ts +19 -0
  17. package/dist/cache/search-cache.d.ts.map +1 -0
  18. package/dist/client.cjs +423 -0
  19. package/dist/client.cjs.map +1 -0
  20. package/dist/client.d.cts +12 -0
  21. package/dist/client.d.ts +12 -0
  22. package/dist/client.d.ts.map +1 -0
  23. package/dist/client.js +388 -0
  24. package/dist/client.js.map +1 -0
  25. package/dist/commercetools/build-search-keywords.d.ts +37 -0
  26. package/dist/commercetools/build-search-keywords.d.ts.map +1 -0
  27. package/dist/commercetools/cart.d.ts +70 -0
  28. package/dist/commercetools/cart.d.ts.map +1 -0
  29. package/dist/commercetools/checkout.d.ts +33 -0
  30. package/dist/commercetools/checkout.d.ts.map +1 -0
  31. package/dist/commercetools/client.d.ts +43 -0
  32. package/dist/commercetools/client.d.ts.map +1 -0
  33. package/dist/commercetools/facet-color.d.ts +12 -0
  34. package/dist/commercetools/facet-color.d.ts.map +1 -0
  35. package/dist/commercetools/facets.d.ts +31 -0
  36. package/dist/commercetools/facets.d.ts.map +1 -0
  37. package/dist/commercetools/graphql-product-cards.d.ts +94 -0
  38. package/dist/commercetools/graphql-product-cards.d.ts.map +1 -0
  39. package/dist/commercetools/order.d.ts +27 -0
  40. package/dist/commercetools/order.d.ts.map +1 -0
  41. package/dist/commercetools/payment-map.d.ts +18 -0
  42. package/dist/commercetools/payment-map.d.ts.map +1 -0
  43. package/dist/commercetools/payment.d.ts +28 -0
  44. package/dist/commercetools/payment.d.ts.map +1 -0
  45. package/dist/commercetools/product-card-hydrate.d.ts +25 -0
  46. package/dist/commercetools/product-card-hydrate.d.ts.map +1 -0
  47. package/dist/commercetools/product-types.d.ts +34 -0
  48. package/dist/commercetools/product-types.d.ts.map +1 -0
  49. package/dist/commercetools/query-builder.d.ts +41 -0
  50. package/dist/commercetools/query-builder.d.ts.map +1 -0
  51. package/dist/commercetools/search-helpers.d.ts +16 -0
  52. package/dist/commercetools/search-helpers.d.ts.map +1 -0
  53. package/dist/commercetools/suggestion-quality.d.ts +13 -0
  54. package/dist/commercetools/suggestion-quality.d.ts.map +1 -0
  55. package/dist/commercetools/suggestions.d.ts +3 -0
  56. package/dist/commercetools/suggestions.d.ts.map +1 -0
  57. package/dist/index.cjs +6066 -0
  58. package/dist/index.cjs.map +1 -0
  59. package/dist/index.d.cts +42 -0
  60. package/dist/index.d.ts +42 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +5939 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/locale/resolve.d.ts +16 -0
  65. package/dist/locale/resolve.d.ts.map +1 -0
  66. package/dist/messages/index.d.ts +110 -0
  67. package/dist/messages/index.d.ts.map +1 -0
  68. package/dist/observability/enabled.d.ts +15 -0
  69. package/dist/observability/enabled.d.ts.map +1 -0
  70. package/dist/observability/index.d.ts +8 -0
  71. package/dist/observability/index.d.ts.map +1 -0
  72. package/dist/observability/redact.d.ts +9 -0
  73. package/dist/observability/redact.d.ts.map +1 -0
  74. package/dist/observability/spans.d.ts +20 -0
  75. package/dist/observability/spans.d.ts.map +1 -0
  76. package/dist/observability/wrap-ai-provider.d.ts +14 -0
  77. package/dist/observability/wrap-ai-provider.d.ts.map +1 -0
  78. package/dist/payments/types.d.ts +35 -0
  79. package/dist/payments/types.d.ts.map +1 -0
  80. package/dist/prompts/catalog.d.ts +20 -0
  81. package/dist/prompts/catalog.d.ts.map +1 -0
  82. package/dist/prompts/fragments.d.ts +9 -0
  83. package/dist/prompts/fragments.d.ts.map +1 -0
  84. package/dist/prompts/index.d.ts +35 -0
  85. package/dist/prompts/index.d.ts.map +1 -0
  86. package/dist/prompts/resolve.d.ts +35 -0
  87. package/dist/prompts/resolve.d.ts.map +1 -0
  88. package/dist/prompts/schemas.d.ts +206 -0
  89. package/dist/prompts/schemas.d.ts.map +1 -0
  90. package/dist/search/compound-shopping-list.d.ts +6 -0
  91. package/dist/search/compound-shopping-list.d.ts.map +1 -0
  92. package/dist/search/mission.d.ts +14 -0
  93. package/dist/search/mission.d.ts.map +1 -0
  94. package/dist/search/orchestrator.d.ts +29 -0
  95. package/dist/search/orchestrator.d.ts.map +1 -0
  96. package/dist/search/query-passthrough.d.ts +12 -0
  97. package/dist/search/query-passthrough.d.ts.map +1 -0
  98. package/dist/search/relax-search.d.ts +8 -0
  99. package/dist/search/relax-search.d.ts.map +1 -0
  100. package/dist/search/suggestions-input.d.ts +35 -0
  101. package/dist/search/suggestions-input.d.ts.map +1 -0
  102. package/dist/search/voice-tts.d.ts +6 -0
  103. package/dist/search/voice-tts.d.ts.map +1 -0
  104. package/dist/types/index.d.ts +510 -0
  105. package/dist/types/index.d.ts.map +1 -0
  106. package/dist/utils/audio.d.ts +4 -0
  107. package/dist/utils/audio.d.ts.map +1 -0
  108. package/dist/utils/dev-trace.d.ts +2 -0
  109. package/dist/utils/dev-trace.d.ts.map +1 -0
  110. package/dist/utils/hash.d.ts +2 -0
  111. package/dist/utils/hash.d.ts.map +1 -0
  112. package/dist/utils/model-json.d.ts +4 -0
  113. package/dist/utils/model-json.d.ts.map +1 -0
  114. package/dist/utils/search-timer.d.ts +11 -0
  115. package/dist/utils/search-timer.d.ts.map +1 -0
  116. package/dist/utils/with-timeout.d.ts +6 -0
  117. package/dist/utils/with-timeout.d.ts.map +1 -0
  118. package/package.json +86 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # @commerce-ai-tool/core
2
+
3
+ ## 2.4.0
4
+
5
+ ### Initial public release
6
+
7
+ First published version of the Commerce AI Tool plugin (product roadmap through v2.4).
8
+
9
+ - AI-powered commercetools Product Search (OpenRouter or AWS Bedrock) with voice, text, and image input
10
+ - Autocomplete via Search Term Suggestions, AI suggestion fallback, and AI-suggested facets
11
+ - Optional `primaryTerm` boosting, multi-keyword OR search, and empty-result retries (drop soft filters, then match the primary phrase)
12
+ - Product-card hydrate via GraphQL after ID-only Product Search
13
+ - Anonymous and authenticated carts, host-routed checkout, payment provider hooks, and order confirmation
14
+ - Multi-item shopping missions (compound queries split into parallel Product Search calls)
15
+ - Opt-in Langfuse observability
16
+ - Browser-safe `@commerce-ai-tool/core/client` export for widgets (types, messages, facet helpers). Do not install `core` in a frontend-only app; `@commerce-ai-tool/server` pulls the full package on the backend.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Commerce AI Tool Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @commerce-ai-tool/core
2
+
3
+ Framework-agnostic search logic, AI adapters, and the commercetools client for [Commerce AI Tool](https://github.com/tomasz-miller/commerce-ai-tool).
4
+
5
+ Host storefronts should not install this package in the browser app. Install `@commerce-ai-tool/server` on the backend; it depends on `core`. The React and Angular widgets bundle a small client-safe surface and do not declare `core` as a runtime dependency.
6
+
7
+ ```bash
8
+ pnpm add @commerce-ai-tool/server
9
+ ```
10
+
11
+ Setup: [Getting started](https://github.com/tomasz-miller/commerce-ai-tool/blob/main/docs/GETTING-STARTED.md).
@@ -0,0 +1,5 @@
1
+ import type { AIConfig } from "../types/index.js";
2
+ import type { AIProvider } from "./types.js";
3
+ export type { AIProvider } from "./types.js";
4
+ export declare function createAIProvider(config: AIConfig): AIProvider;
5
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/ai/factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAa7D"}
@@ -0,0 +1,3 @@
1
+ export type { AIProvider } from "./types.js";
2
+ export { createAIProvider } from "./factory.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Detect when OpenRouter rejected `json_schema` so we can retry `json_object`. */
2
+ export declare function isJsonSchemaUnsupportedMessage(body: string): boolean;
3
+ export declare function isJsonSchemaUnsupportedError(error: unknown): boolean;
4
+ //# sourceMappingURL=json-schema-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-errors.d.ts","sourceRoot":"","sources":["../../src/ai/json-schema-errors.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAapE;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGpE"}
@@ -0,0 +1,19 @@
1
+ import type { BedrockConfig, FacetAttributeDefinition, SearchLocaleContext, VoiceAudioInterpretation } from "../../types/index.js";
2
+ import type { AIProvider } from "../types.js";
3
+ export declare class BedrockProvider implements AIProvider {
4
+ private readonly client;
5
+ private readonly modelId;
6
+ private readonly visionModelId;
7
+ constructor(config: BedrockConfig);
8
+ interpretTextQuery(text: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<import("../../client.js").InterpretedSearchQuery>;
9
+ interpretRefineQuery(text: string, context: Parameters<AIProvider["interpretRefineQuery"]>[1], locales: SearchLocaleContext): Promise<import("../../client.js").InterpretedSearchQuery>;
10
+ interpretImageQuery(imageBase64: string, mimeType: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<import("../../client.js").InterpretedSearchQuery>;
11
+ interpretVoiceAudio(_audio: Uint8Array, _mimeType: string, _locales: SearchLocaleContext, _attributeCatalog?: FacetAttributeDefinition[]): Promise<VoiceAudioInterpretation>;
12
+ enhanceVoiceTranscript(transcript: string, locales: SearchLocaleContext): Promise<string>;
13
+ suggestSearchTerms(query: string, locales: SearchLocaleContext, limit?: number): Promise<string[]>;
14
+ summarizeVoiceResults(count: number, topProductName: string | undefined, locales: SearchLocaleContext): Promise<string>;
15
+ decomposeShoppingMission(text: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<import("../../client.js").DecomposedShoppingMission>;
16
+ private converse;
17
+ private extractText;
18
+ }
19
+ //# sourceMappingURL=bedrock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/bedrock.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,aAAa,EACb,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAuB9C,qBAAa,eAAgB,YAAW,UAAU;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC,YAAY,MAAM,EAAE,aAAa,EAIhC;IAEK,kBAAkB,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,GAAE,wBAAwB,EAAO,6DAoBlD;IAEK,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1D,OAAO,EAAE,mBAAmB,6DAkB7B;IAEK,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,GAAE,wBAAwB,EAAO,6DA2BlD;IAEK,mBAAmB,CACvB,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,mBAAmB,EAC7B,iBAAiB,CAAC,EAAE,wBAAwB,EAAE,GAC7C,OAAO,CAAC,wBAAwB,CAAC,CAInC;IAEK,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,mBAc5E;IAEK,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,SAAI,qBAiB9E;IAEK,qBAAqB,CACzB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,OAAO,EAAE,mBAAmB,mBAe7B;IAEK,wBAAwB,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,GAAE,wBAAwB,EAAO,gEAkBlD;YAEa,QAAQ;IAUtB,OAAO,CAAC,WAAW;CAWpB"}
@@ -0,0 +1,27 @@
1
+ import type { FacetAttributeDefinition, OpenRouterConfig, SearchLocaleContext } from "../../types/index.js";
2
+ import type { AIProvider, GenerationMetrics } from "../types.js";
3
+ export declare class OpenRouterProvider implements AIProvider {
4
+ private readonly client;
5
+ private readonly apiKey;
6
+ private readonly model;
7
+ private readonly visionModel;
8
+ private readonly voiceModel;
9
+ private readonly useJsonSchema;
10
+ private lastMetrics;
11
+ constructor(config: OpenRouterConfig);
12
+ getLastGenerationMetrics(): GenerationMetrics | undefined;
13
+ interpretTextQuery(text: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<import("../../client.js").InterpretedSearchQuery>;
14
+ interpretRefineQuery(text: string, context: Parameters<AIProvider["interpretRefineQuery"]>[1], locales: SearchLocaleContext): Promise<import("../../client.js").InterpretedSearchQuery>;
15
+ interpretImageQuery(imageBase64: string, mimeType: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<import("../../client.js").InterpretedSearchQuery>;
16
+ interpretVoiceAudio(audio: Uint8Array, mimeType: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<import("../../client.js").VoiceAudioInterpretation>;
17
+ enhanceVoiceTranscript(transcript: string, locales: SearchLocaleContext): Promise<string>;
18
+ suggestSearchTerms(query: string, locales: SearchLocaleContext, limit?: number): Promise<string[]>;
19
+ summarizeVoiceResults(count: number, topProductName: string | undefined, locales: SearchLocaleContext): Promise<string>;
20
+ decomposeShoppingMission(text: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<import("../../client.js").DecomposedShoppingMission>;
21
+ private sendStructured;
22
+ private toApiResponseFormat;
23
+ private sendChatCompletion;
24
+ private captureUsage;
25
+ private extractContent;
26
+ }
27
+ //# sourceMappingURL=openrouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/openrouter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC5G,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAoCjE,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,WAAW,CAAgC;IAEnD,YAAY,MAAM,EAAE,gBAAgB,EAOnC;IAED,wBAAwB,IAAI,iBAAiB,GAAG,SAAS,CAExD;IAEK,kBAAkB,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,GAAE,wBAAwB,EAAO,6DAiBlD;IAEK,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1D,OAAO,EAAE,mBAAmB,6DAY7B;IAEK,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,GAAE,wBAAwB,EAAO,6DAsBlD;IAEK,mBAAmB,CACvB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,GAAE,wBAAwB,EAAO,+DAsClD;IAEK,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,mBAe5E;IAEK,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,SAAI,qBAc9E;IAEK,qBAAqB,CACzB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,OAAO,EAAE,mBAAmB,mBAgB7B;IAEK,wBAAwB,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,GAAE,wBAAwB,EAAO,gEAelD;YAEa,cAAc;IAsC5B,OAAO,CAAC,mBAAmB;YAcb,kBAAkB;IAwChC,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,cAAc;CAqBvB"}
@@ -0,0 +1,23 @@
1
+ import type { DecomposedShoppingMission, FacetAttributeDefinition, InterpretedSearchFilters, InterpretedSearchQuery, SearchLocaleContext, VoiceAudioInterpretation } from "../types/index.js";
2
+ export interface GenerationMetrics {
3
+ promptTokens?: number;
4
+ completionTokens?: number;
5
+ totalTokens?: number;
6
+ cost?: number;
7
+ }
8
+ export interface AIProvider {
9
+ interpretTextQuery(text: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<InterpretedSearchQuery>;
10
+ interpretRefineQuery(text: string, context: {
11
+ searchTerms: string[];
12
+ filters: InterpretedSearchFilters;
13
+ attributeCatalog: FacetAttributeDefinition[];
14
+ }, locales: SearchLocaleContext): Promise<InterpretedSearchQuery>;
15
+ interpretImageQuery(imageBase64: string, mimeType: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<InterpretedSearchQuery>;
16
+ interpretVoiceAudio(audio: Uint8Array, mimeType: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<VoiceAudioInterpretation>;
17
+ enhanceVoiceTranscript(transcript: string, locales: SearchLocaleContext): Promise<string>;
18
+ suggestSearchTerms(query: string, locales: SearchLocaleContext, limit?: number): Promise<string[]>;
19
+ summarizeVoiceResults(count: number, topProductName: string | undefined, locales: SearchLocaleContext): Promise<string>;
20
+ decomposeShoppingMission(text: string, locales: SearchLocaleContext, attributeCatalog?: FacetAttributeDefinition[]): Promise<DecomposedShoppingMission>;
21
+ getLastGenerationMetrics?(): GenerationMetrics | undefined;
22
+ }
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ai/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,CAAC,EAAE,wBAAwB,EAAE,GAC5C,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnC,oBAAoB,CAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,OAAO,EAAE,wBAAwB,CAAC;QAClC,gBAAgB,EAAE,wBAAwB,EAAE,CAAC;KAC9C,EACD,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnC,mBAAmB,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,CAAC,EAAE,wBAAwB,EAAE,GAC5C,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnC,mBAAmB,CACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,CAAC,EAAE,wBAAwB,EAAE,GAC5C,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACrC,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1F,kBAAkB,CAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,EAC5B,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACrB,qBAAqB,CACnB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,wBAAwB,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,CAAC,EAAE,wBAAwB,EAAE,GAC5C,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACtC,wBAAwB,CAAC,IAAI,iBAAiB,GAAG,SAAS,CAAC;CAC5D"}
@@ -0,0 +1,19 @@
1
+ export interface SearchCacheConfig {
2
+ ttlMs?: number;
3
+ maxEntries?: number;
4
+ }
5
+ export declare class SearchCache<T> {
6
+ private readonly ttlMs;
7
+ private readonly maxEntries;
8
+ private readonly store;
9
+ constructor(config?: SearchCacheConfig);
10
+ get(key: string): T | undefined;
11
+ set(key: string, value: T): void;
12
+ }
13
+ export declare function normalizeCacheKeyPart(value: string): string;
14
+ export declare function buildTextSearchCacheKey(query: string, queryLocale: string, catalogLocale: string, limit: number): string;
15
+ export declare function buildInterpretedSearchCacheKey(interpretedKey: string, catalogLocale: string, limit: number): string;
16
+ export declare function buildSuggestionsCacheKey(query: string, suggestLocale: string, limit: number): string;
17
+ export declare function buildImageSearchCacheKey(imageHash: string, mimeType: string, queryLocale: string, catalogLocale: string, limit: number, missionsEnabled?: boolean): string;
18
+ export declare function buildVoiceSearchCacheKey(audioHash: string, mimeType: string, voiceMode: string, queryLocale: string, catalogLocale: string, limit: number, enableTts: boolean, missionsEnabled?: boolean): string;
19
+ //# sourceMappingURL=search-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-cache.d.ts","sourceRoot":"","sources":["../../src/cache/search-cache.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,qBAAa,WAAW,CAAC,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAE1D,YAAY,MAAM,CAAC,EAAE,iBAAiB,EAGrC;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAY9B;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAY/B;CACF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,GACZ,MAAM,CAQR;AAED,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,GACZ,MAAM,CAER;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,GACZ,MAAM,CAOR;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,eAAe,UAAQ,GACtB,MAAM,CAUR;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,EAClB,eAAe,UAAQ,GACtB,MAAM,CAYR"}
@@ -0,0 +1,423 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/client.ts
21
+ var client_exports = {};
22
+ __export(client_exports, {
23
+ CART_SESSION_HEADER: () => CART_SESSION_HEADER,
24
+ DEFAULT_COMMERCE_AI_SEARCH_MESSAGES: () => DEFAULT_COMMERCE_AI_SEARCH_MESSAGES,
25
+ MAX_LINE_ITEM_QUANTITY: () => MAX_LINE_ITEM_QUANTITY,
26
+ hexColorSwatchValue: () => hexColorSwatchValue,
27
+ isColorLikeFacetName: () => isColorLikeFacetName,
28
+ isFacetFilterSelected: () => isFacetFilterSelected,
29
+ looksLikeCompoundShoppingList: () => looksLikeCompoundShoppingList,
30
+ resolveCommerceAISearchMessages: () => resolveCommerceAISearchMessages,
31
+ toggleFacetFilter: () => toggleFacetFilter
32
+ });
33
+ module.exports = __toCommonJS(client_exports);
34
+
35
+ // src/types/index.ts
36
+ var CART_SESSION_HEADER = "x-commerce-ai-cart-session";
37
+ var MAX_LINE_ITEM_QUANTITY = 99;
38
+
39
+ // src/messages/index.ts
40
+ var DEFAULT_COMMERCE_AI_SEARCH_MESSAGES = {
41
+ placeholder: "What are you looking for?",
42
+ searchAriaLabel: "Search query",
43
+ productSearchAriaLabel: "Product search",
44
+ searchResultsAriaLabel: "Search results",
45
+ searching: "Searching...",
46
+ noProductsFound: "No products found",
47
+ searchedFor: "Searched for:",
48
+ dropImageToSearch: "Drop image to search",
49
+ voiceSearch: "Voice search",
50
+ stopRecording: "Stop recording",
51
+ searchByCamera: "Search by camera",
52
+ searchByImage: "Search by image",
53
+ replayVoiceSummary: "Replay voice result summary",
54
+ listening: "Listening\u2026",
55
+ tapMicToStop: "Tap mic to stop",
56
+ understandingQuery: "Understanding your query\u2026",
57
+ preparingAudioSummary: "Preparing audio summary\u2026",
58
+ cameraCapture: "Camera capture",
59
+ cameraPreview: "Camera preview",
60
+ capturePhoto: "Capture",
61
+ cancel: "Cancel",
62
+ dismiss: "Dismiss",
63
+ searchFailed: "Search failed",
64
+ imageSearchFailed: "Image search failed",
65
+ couldNotCapturePhoto: "Could not capture photo",
66
+ suggestionsAriaLabel: "Search suggestions",
67
+ loadingSuggestions: "Loading suggestions...",
68
+ noSuggestions: "No suggestions",
69
+ filtersAriaLabel: "Search filters",
70
+ clearFilters: "Clear filters",
71
+ narrowResults: "Narrow your results",
72
+ newSearch: "New search",
73
+ addToCart: "Add to cart",
74
+ cart: "Cart",
75
+ emptyCart: "Your cart is empty",
76
+ removeItem: "Remove item",
77
+ total: "Total",
78
+ each: "each",
79
+ cartAriaLabel: "Shopping cart",
80
+ itemAdded: "Added to cart",
81
+ increaseQuantity: "Increase quantity",
82
+ decreaseQuantity: "Decrease quantity",
83
+ closeCart: "Close cart",
84
+ unableToAddToCart: "This product cannot be added to the cart",
85
+ missionTitle: "Shopping list",
86
+ missionQuantity: "Looking for",
87
+ missionAddAll: "Add {count} top picks to cart",
88
+ missionItemsAdded: "Added to cart",
89
+ missionSelectProduct: "Select this product",
90
+ missionIntentEmpty: "No matching products",
91
+ missionIntentFailed: "Couldn't search this item",
92
+ signIn: "Sign in",
93
+ signInToSyncCart: "Sign in to sync your cart",
94
+ signOut: "Sign out",
95
+ email: "Email",
96
+ password: "Password",
97
+ signedInAs: "Signed in as",
98
+ invalidCredentials: "Invalid email or password",
99
+ signInFailed: "Sign in failed",
100
+ checkout: "Checkout",
101
+ checkoutTitle: "Complete your order",
102
+ orderSummary: "Order summary",
103
+ shippingAddress: "Shipping address",
104
+ billingAddress: "Billing address",
105
+ billingSameAsShipping: "Billing address is the same as shipping",
106
+ continueToDelivery: "Continue to delivery",
107
+ shippingMethod: "Delivery method",
108
+ selectShippingMethod: "Select a delivery method",
109
+ noShippingMethods: "No delivery methods are available for this address",
110
+ completeAddressToContinue: "Add a shipping address to continue",
111
+ selectDeliveryToContinue: "Select a delivery method to continue",
112
+ selectPaymentToContinue: "Select a payment method to continue",
113
+ checkoutStepAddress: "Address",
114
+ checkoutStepDelivery: "Delivery",
115
+ checkoutStepPayment: "Payment",
116
+ paymentMethod: "Payment method",
117
+ selectPaymentMethod: "Select a payment method",
118
+ paymentAuthorized: "Payment authorized",
119
+ paymentDeclined: "Payment was declined",
120
+ continueToPayment: "Continue to payment",
121
+ placeOrder: "Place order",
122
+ placingOrder: "Placing order\u2026",
123
+ orderPlaced: "Order placed",
124
+ viewOrderStatus: "View order status",
125
+ continueShopping: "Continue shopping",
126
+ checkoutFailed: "Checkout failed",
127
+ orderStatus: "Order status",
128
+ orderPlacedAt: "Placed",
129
+ paymentStateLabel: "Payment",
130
+ shipmentStateLabel: "Shipment",
131
+ trackingNumber: "Tracking number",
132
+ carrier: "Carrier",
133
+ noTrackingYet: "Tracking details will appear when the order ships",
134
+ orderNotFound: "Order not found",
135
+ noOrdersYet: "No orders yet",
136
+ yourOrders: "Your orders",
137
+ firstName: "First name",
138
+ lastName: "Last name",
139
+ streetName: "Street address",
140
+ additionalAddress: "Apartment, suite, etc. (optional)",
141
+ postalCode: "Postal code",
142
+ city: "City",
143
+ region: "State or region (optional)",
144
+ country: "Country"
145
+ };
146
+ function resolveCommerceAISearchMessages(overrides) {
147
+ return {
148
+ ...DEFAULT_COMMERCE_AI_SEARCH_MESSAGES,
149
+ ...overrides
150
+ };
151
+ }
152
+
153
+ // src/search/compound-shopping-list.ts
154
+ var COMPOUND_SHOPPING_LIST_PATTERN = /\band\b|,|\bplus\b|\boraz\b/i;
155
+ function looksLikeCompoundShoppingList(query) {
156
+ return COMPOUND_SHOPPING_LIST_PATTERN.test(query.trim());
157
+ }
158
+
159
+ // src/commercetools/facet-color.ts
160
+ var CSS_NAMED_COLOR_TABLE = `
161
+ Alice Blue:f0f8ff
162
+ Antique White:faebd7
163
+ Aqua:00ffff
164
+ Aquamarine:7fffd4
165
+ Azure:f0ffff
166
+ Beige:f5f5dc
167
+ Bisque:ffe4c4
168
+ Black:000000
169
+ Blanched Almond:ffebcd
170
+ Blue:0000ff
171
+ Blue Violet:8a2be2
172
+ Brown:a52a2a
173
+ Burlywood:deb887
174
+ Cadet Blue:5f9ea0
175
+ Chartreuse:7fff00
176
+ Chocolate:d2691e
177
+ Coral:ff7f50
178
+ Cornflower Blue:6495ed
179
+ Cornsilk:fff8dc
180
+ Crimson:dc143c
181
+ Dark Blue:00008b
182
+ Dark Cyan:008b8b
183
+ Dark Goldenrod:b8860b
184
+ Dark Gray:a9a9a9
185
+ Dark Green:006400
186
+ Dark Khaki:bdb76b
187
+ Dark Magenta:8b008b
188
+ Dark Olive Green:556b2f
189
+ Dark Orange:ff8c00
190
+ Dark Orchid:9932cc
191
+ Dark Red:8b0000
192
+ Dark Salmon:e9967a
193
+ Dark Sea Green:8fbc8f
194
+ Dark Slate Blue:483d8b
195
+ Dark Slate Gray:2f4f4f
196
+ Dark Turquoise:00ced1
197
+ Dark Violet:9400d3
198
+ Deep Pink:ff1493
199
+ Deep Sky Blue:00bfff
200
+ Dim Gray:696969
201
+ Dodger Blue:1e90ff
202
+ Firebrick:b22222
203
+ Floral White:fffaf0
204
+ Forest Green:228b22
205
+ Gainsboro:dcdcdc
206
+ Ghost White:f8f8ff
207
+ Gold:ffd700
208
+ Goldenrod:daa520
209
+ Gray:808080
210
+ Green:008000
211
+ Green Yellow:adff2f
212
+ Honeydew:f0fff0
213
+ Hot Pink:ff69b4
214
+ Indian Red:cd5c5c
215
+ Indigo:4b0082
216
+ Ivory:fffff0
217
+ Khaki:f0e68c
218
+ Lavender:e6e6fa
219
+ Lavender Blush:fff0f5
220
+ Lawn Green:7cfc00
221
+ Lemon Chiffon:fffacd
222
+ Light Blue:add8e6
223
+ Light Coral:f08080
224
+ Light Cyan:e0ffff
225
+ Light Goldenrod Yellow:fafad2
226
+ Light Gray:d3d3d3
227
+ Light Green:90ee90
228
+ Light Pink:ffb6c1
229
+ Light Salmon:ffa07a
230
+ Light Sea Green:20b2aa
231
+ Light Sky Blue:87cefa
232
+ Light Slate Gray:778899
233
+ Light Steel Blue:b0c4de
234
+ Light Yellow:ffffe0
235
+ Lime:00ff00
236
+ Lime Green:32cd32
237
+ Linen:faf0e6
238
+ Magenta:ff00ff
239
+ Maroon:800000
240
+ Medium Aquamarine:66cdaa
241
+ Medium Blue:0000cd
242
+ Medium Orchid:ba55d3
243
+ Medium Purple:9370db
244
+ Medium Sea Green:3cb371
245
+ Medium Slate Blue:7b68ee
246
+ Medium Spring Green:00fa9a
247
+ Medium Turquoise:48d1cc
248
+ Medium Violet Red:c71585
249
+ Midnight Blue:191970
250
+ Mint Cream:f5fffa
251
+ Misty Rose:ffe4e1
252
+ Moccasin:ffe4b5
253
+ Navajo White:ffdead
254
+ Navy:000080
255
+ Old Lace:fdf5e6
256
+ Olive:808000
257
+ Olive Drab:6b8e23
258
+ Orange:ffa500
259
+ Orange Red:ff4500
260
+ Orchid:da70d6
261
+ Pale Goldenrod:eee8aa
262
+ Pale Green:98fb98
263
+ Pale Turquoise:afeeee
264
+ Pale Violet Red:db7093
265
+ Papaya Whip:ffefd5
266
+ Peach Puff:ffdab9
267
+ Peru:cd853f
268
+ Pink:ffc0cb
269
+ Plum:dda0dd
270
+ Powder Blue:b0e0e6
271
+ Purple:800080
272
+ Rebecca Purple:663399
273
+ Red:ff0000
274
+ Rosy Brown:bc8f8f
275
+ Royal Blue:4169e1
276
+ Saddle Brown:8b4513
277
+ Salmon:fa8072
278
+ Sandy Brown:f4a460
279
+ Sea Green:2e8b57
280
+ Seashell:fff5ee
281
+ Sienna:a0522d
282
+ Silver:c0c0c0
283
+ Sky Blue:87ceeb
284
+ Slate Blue:6a5acd
285
+ Slate Gray:708090
286
+ Snow:fffafa
287
+ Spring Green:00ff7f
288
+ Steel Blue:4682b4
289
+ Tan:d2b48c
290
+ Teal:008080
291
+ Thistle:d8bfd8
292
+ Tomato:ff6347
293
+ Turquoise:40e0d0
294
+ Violet:ee82ee
295
+ Wheat:f5deb3
296
+ White:ffffff
297
+ White Smoke:f5f5f5
298
+ Yellow:ffff00
299
+ Yellow Green:9acd32
300
+ `;
301
+ var HEX_COLOR_RE = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
302
+ var NAMED_COLORS = CSS_NAMED_COLOR_TABLE.trim().split("\n").flatMap((line) => {
303
+ const separator = line.indexOf(":");
304
+ if (separator <= 0) {
305
+ return [];
306
+ }
307
+ const name = line.slice(0, separator);
308
+ const hex = line.slice(separator + 1);
309
+ const n = Number.parseInt(hex, 16);
310
+ if (!name || !Number.isFinite(n)) {
311
+ return [];
312
+ }
313
+ return [{ name, r: n >> 16 & 255, g: n >> 8 & 255, b: n & 255 }];
314
+ });
315
+ function parseHexRgb(value) {
316
+ const match = HEX_COLOR_RE.exec(value.trim());
317
+ const captured = match?.[1];
318
+ if (!captured) {
319
+ return null;
320
+ }
321
+ const hex = captured.length === 3 ? `${captured[0]}${captured[0]}${captured[1]}${captured[1]}${captured[2]}${captured[2]}` : captured;
322
+ const n = Number.parseInt(hex, 16);
323
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
324
+ }
325
+ var MAX_NAMED_COLOR_DISTANCE_SQ = 40 * 40;
326
+ var COLOR_LIKE_FACET_NAME = /(?:^|[-_])colou?r(?:[-_]|$)|(?:^|[-_])finish(?:[-_]|$)/i;
327
+ function isColorLikeFacetName(name) {
328
+ return COLOR_LIKE_FACET_NAME.test(name.trim());
329
+ }
330
+ function hexColorSwatchValue(value) {
331
+ const rgb = parseHexRgb(value);
332
+ if (!rgb) {
333
+ return void 0;
334
+ }
335
+ return `#${rgb.map((channel) => channel.toString(16).padStart(2, "0")).join("")}`;
336
+ }
337
+
338
+ // src/commercetools/facets.ts
339
+ var PRICE_FACET_ID = "price";
340
+ var CATEGORIES_FACET_ID = "categories";
341
+ var DEFAULT_PRICE_RANGES = [
342
+ { key: "under-50", to: 5e3 },
343
+ { key: "50-to-100", from: 5e3, to: 1e4 },
344
+ { key: "100-plus", from: 1e4 }
345
+ ];
346
+ function priceRangeToFilterValues(range) {
347
+ const filters = {};
348
+ if ("from" in range && range.from !== void 0) {
349
+ filters.priceMin = String(range.from / 100);
350
+ }
351
+ if ("to" in range && range.to !== void 0) {
352
+ filters.priceMax = String(range.to / 100);
353
+ }
354
+ return filters;
355
+ }
356
+ function priceBucketKeyFromFilters(filters) {
357
+ const minCents = parseMajorToCents(filters.priceMin);
358
+ const maxCents = parseMajorToCents(filters.priceMax);
359
+ for (const range of DEFAULT_PRICE_RANGES) {
360
+ const from = "from" in range ? range.from : void 0;
361
+ const to = "to" in range ? range.to : void 0;
362
+ if (minCents === from && maxCents === to) {
363
+ return range.key;
364
+ }
365
+ }
366
+ return void 0;
367
+ }
368
+ function isFacetFilterSelected(filters, facetId, bucketKey) {
369
+ if (facetId === CATEGORIES_FACET_ID) {
370
+ return filters.category === bucketKey;
371
+ }
372
+ if (facetId === PRICE_FACET_ID) {
373
+ return priceBucketKeyFromFilters(filters) === bucketKey;
374
+ }
375
+ return filters[facetId] === bucketKey;
376
+ }
377
+ function toggleFacetFilter(filters, facetId, bucketKey) {
378
+ const next = { ...filters };
379
+ if (facetId === PRICE_FACET_ID) {
380
+ if (priceBucketKeyFromFilters(next) === bucketKey) {
381
+ delete next.priceMin;
382
+ delete next.priceMax;
383
+ return next;
384
+ }
385
+ delete next.priceMin;
386
+ delete next.priceMax;
387
+ const range = DEFAULT_PRICE_RANGES.find((candidate) => candidate.key === bucketKey);
388
+ if (!range) {
389
+ return next;
390
+ }
391
+ return { ...next, ...priceRangeToFilterValues(range) };
392
+ }
393
+ const filterKey = facetId === CATEGORIES_FACET_ID ? "category" : facetId;
394
+ if (next[filterKey] === bucketKey) {
395
+ delete next[filterKey];
396
+ } else {
397
+ next[filterKey] = bucketKey;
398
+ }
399
+ return next;
400
+ }
401
+ function parseMajorToCents(value) {
402
+ if (!value) {
403
+ return void 0;
404
+ }
405
+ const parsed = Number(value);
406
+ if (!Number.isFinite(parsed) || parsed < 0) {
407
+ return void 0;
408
+ }
409
+ return Math.round(parsed * 100);
410
+ }
411
+ // Annotate the CommonJS export names for ESM import in node:
412
+ 0 && (module.exports = {
413
+ CART_SESSION_HEADER,
414
+ DEFAULT_COMMERCE_AI_SEARCH_MESSAGES,
415
+ MAX_LINE_ITEM_QUANTITY,
416
+ hexColorSwatchValue,
417
+ isColorLikeFacetName,
418
+ isFacetFilterSelected,
419
+ looksLikeCompoundShoppingList,
420
+ resolveCommerceAISearchMessages,
421
+ toggleFacetFilter
422
+ });
423
+ //# sourceMappingURL=client.cjs.map