@primestyleai/tryon 5.10.86 → 5.10.87

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.
@@ -3,6 +3,13 @@ export interface TryOnContext {
3
3
  /** Storefront product the customer is currently viewing — shown in analytics. */
4
4
  productId?: string;
5
5
  productTitle?: string;
6
+ /** Free-text product description forwarded to the try-on prompt so Gemini
7
+ * knows the garment context (e.g. "Brown slip maxi dress, spaghetti straps"). */
8
+ productDescription?: string;
9
+ /** Material / fabric composition (e.g. "100% Cotton", "60% Polyester / 40% Polyester")
10
+ * — forwarded to the prompt so Gemini drapes the fabric correctly without
11
+ * having to guess from the image alone. */
12
+ productMaterial?: string;
6
13
  /** Optional silhouette-prompt context forwarded to the backend Gemini try-on
7
14
  * call. Enables doc-example-grade fit reasoning ("X tension at button
8
15
  * because waist 54.4 exceeds size 50 drop"). All fields optional. */
@@ -62,7 +62,7 @@ class q {
62
62
  Authorization: `Bearer ${this.apiKey}`
63
63
  };
64
64
  }
65
- async submitTryOn(e, t, i, s, a) {
65
+ async submitTryOn(e, t, r, s, i) {
66
66
  const n = {
67
67
  garmentImage: t,
68
68
  // Attribution fields — backend logs these into the TryOnEvent collection
@@ -71,27 +71,27 @@ class q {
71
71
  sessionId: T(),
72
72
  deviceHint: b()
73
73
  };
74
- if (a?.modelImageId && (n.modelImageId = a.modelImageId), e && (n.modelImage = e), i && i.length > 0 && (n.fitInfo = i), s && s !== "apparel" && (n.category = s), a?.productId && (n.productId = a.productId), a?.productTitle && (n.productTitle = a.productTitle), a?.silhouetteContext && (n.silhouetteContext = a.silhouetteContext), a?.editFromPrevious && (n.editFromPrevious = !0), console.log("[ps-sdk:api] POST /api/v1/tryon payload", {
74
+ if (i?.modelImageId && (n.modelImageId = i.modelImageId), e && (n.modelImage = e), r && r.length > 0 && (n.fitInfo = r), s && s !== "apparel" && (n.category = s), i?.productId && (n.productId = i.productId), i?.productTitle && (n.productTitle = i.productTitle), i?.productDescription && (n.productDescription = i.productDescription), i?.productMaterial && (n.productMaterial = i.productMaterial), i?.silhouetteContext && (n.silhouetteContext = i.silhouetteContext), i?.editFromPrevious && (n.editFromPrevious = !0), console.log("[ps-sdk:api] POST /api/v1/tryon payload", {
75
75
  modelImageBytes: e.length,
76
76
  garmentImageBytes: t.length,
77
77
  category: s || "apparel",
78
- fitInfo: i?.map((r) => ({
79
- area: r.area,
80
- fit: r.fit,
81
- userValue: r.userValue,
82
- garmentRange: r.garmentRange
78
+ fitInfo: r?.map((a) => ({
79
+ area: a.area,
80
+ fit: a.fit,
81
+ userValue: a.userValue,
82
+ garmentRange: a.garmentRange
83
83
  })) || null,
84
- silhouetteContext: a?.silhouetteContext || null
85
- }), i && i.length > 0) {
84
+ silhouetteContext: i?.silhouetteContext || null
85
+ }), r && r.length > 0) {
86
86
  console.log("[ps-sdk:api] Body vs Garment (what Gemini will see):");
87
- for (const r of i) {
88
- const l = (r.garmentRange || "").replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((h) => !isNaN(h));
87
+ for (const a of r) {
88
+ const l = (a.garmentRange || "").replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((h) => !isNaN(h));
89
89
  let u = "";
90
- if (l.length && r.userValue != null) {
91
- const h = (Math.min(...l) + Math.max(...l)) / 2, g = Math.round((r.userValue - h) * 10) / 10;
90
+ if (l.length && a.userValue != null) {
91
+ const h = (Math.min(...l) + Math.max(...l)) / 2, g = Math.round((a.userValue - h) * 10) / 10;
92
92
  u = g > 0 ? `garment ${g} smaller` : g < 0 ? `garment ${Math.abs(g)} larger` : "matched";
93
93
  }
94
- console.log(`[ps-sdk:api] ${r.area.padEnd(10)} body=${r.userValue ?? "?"} garment=${r.garmentRange ?? "?"} → ${u}`);
94
+ console.log(`[ps-sdk:api] ${a.area.padEnd(10)} body=${a.userValue ?? "?"} garment=${a.garmentRange ?? "?"} → ${u}`);
95
95
  }
96
96
  }
97
97
  const d = await fetch(`${this.baseUrl}/api/v1/tryon`, {
@@ -100,12 +100,12 @@ class q {
100
100
  body: JSON.stringify(n)
101
101
  });
102
102
  if (!d.ok) {
103
- const r = await d.json().catch(() => ({}));
103
+ const a = await d.json().catch(() => ({}));
104
104
  throw d.status === 402 ? new y(
105
- r.message || "Insufficient try-ons",
105
+ a.message || "Insufficient try-ons",
106
106
  "INSUFFICIENT_BALANCE"
107
107
  ) : new y(
108
- r.message || "Failed to submit try-on",
108
+ a.message || "Failed to submit try-on",
109
109
  "API_ERROR"
110
110
  );
111
111
  }
@@ -116,9 +116,9 @@ class q {
116
116
  headers: this.headers
117
117
  });
118
118
  if (!t.ok) {
119
- const i = await t.json().catch(() => ({}));
119
+ const r = await t.json().catch(() => ({}));
120
120
  throw new y(
121
- i.message || "Failed to get status",
121
+ r.message || "Failed to get status",
122
122
  "API_ERROR"
123
123
  );
124
124
  }
@@ -159,13 +159,13 @@ class _ {
159
159
  }
160
160
  onJob(e, t) {
161
161
  return this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set()), this.listeners.get(e).add(t), this.eventSource || this.connect(), () => {
162
- const i = this.listeners.get(e);
163
- i && (i.delete(t), i.size === 0 && this.listeners.delete(e)), this.listeners.size === 0 && this.disconnect();
162
+ const r = this.listeners.get(e);
163
+ r && (r.delete(t), r.size === 0 && this.listeners.delete(e)), this.listeners.size === 0 && this.disconnect();
164
164
  };
165
165
  }
166
166
  emit(e, t) {
167
- const i = this.listeners.get(e);
168
- i && i.forEach((s) => s(t));
167
+ const r = this.listeners.get(e);
168
+ r && r.forEach((s) => s(t));
169
169
  }
170
170
  disconnect() {
171
171
  this.reconnectTimer && (clearTimeout(this.reconnectTimer), this.reconnectTimer = null), this.eventSource && (this.eventSource.close(), this.eventSource = null), this.listeners.clear(), this.reconnectAttempts = 0;
@@ -173,29 +173,29 @@ class _ {
173
173
  }
174
174
  const z = 512, A = 0.65;
175
175
  function M(o, e = {}) {
176
- const t = e.maxDimension ?? z, i = e.quality ?? A;
177
- return new Promise((s, a) => {
176
+ const t = e.maxDimension ?? z, r = e.quality ?? A;
177
+ return new Promise((s, i) => {
178
178
  const n = new FileReader();
179
179
  n.onload = () => {
180
180
  const d = new Image();
181
181
  d.onload = () => {
182
182
  try {
183
- const r = document.createElement("canvas");
183
+ const a = document.createElement("canvas");
184
184
  let { width: l, height: u } = d;
185
- (l > t || u > t) && (l > u ? (u = Math.round(u * t / l), l = t) : (l = Math.round(l * t / u), u = t)), r.width = l, r.height = u;
186
- const h = r.getContext("2d");
185
+ (l > t || u > t) && (l > u ? (u = Math.round(u * t / l), l = t) : (l = Math.round(l * t / u), u = t)), a.width = l, a.height = u;
186
+ const h = a.getContext("2d");
187
187
  if (!h) {
188
- a(new Error("Canvas context not available"));
188
+ i(new Error("Canvas context not available"));
189
189
  return;
190
190
  }
191
191
  h.drawImage(d, 0, 0, l, u);
192
- const g = r.toDataURL("image/jpeg", i);
192
+ const g = a.toDataURL("image/jpeg", r);
193
193
  s(g);
194
- } catch (r) {
195
- a(r);
194
+ } catch (a) {
195
+ i(a);
196
196
  }
197
- }, d.onerror = () => a(new Error("Failed to load image")), d.src = n.result;
198
- }, n.onerror = () => a(new Error("Failed to read file")), n.readAsDataURL(o);
197
+ }, d.onerror = () => i(new Error("Failed to load image")), d.src = n.result;
198
+ }, n.onerror = () => i(new Error("Failed to read file")), n.readAsDataURL(o);
199
199
  });
200
200
  }
201
201
  function $(o) {
@@ -203,25 +203,25 @@ function $(o) {
203
203
  }
204
204
  async function X(o, e, t) {
205
205
  try {
206
- const i = typeof o == "string" ? o : await M(o, { maxDimension: 384, quality: 0.6 }), s = await fetch(`${e}/api/v1/sizing/age-check`, {
206
+ const r = typeof o == "string" ? o : await M(o, { maxDimension: 384, quality: 0.6 }), s = await fetch(`${e}/api/v1/sizing/age-check`, {
207
207
  method: "POST",
208
208
  headers: {
209
209
  "Content-Type": "application/json",
210
210
  Authorization: `Bearer ${t}`
211
211
  },
212
- body: JSON.stringify({ bodyImage: i })
212
+ body: JSON.stringify({ bodyImage: r })
213
213
  });
214
214
  if (!s.ok)
215
215
  return console.warn(`[PS-SDK:AgeCheck] HTTP ${s.status} — failing open`), { isAdult: !0, confidence: "low" };
216
- const a = await s.json();
216
+ const i = await s.json();
217
217
  return {
218
- isAdult: a?.isAdult !== !1,
218
+ isAdult: i?.isAdult !== !1,
219
219
  // anything other than explicit false → allow
220
- confidence: a?.confidence === "high" ? "high" : "low",
221
- reasoning: typeof a?.reasoning == "string" ? a.reasoning : void 0
220
+ confidence: i?.confidence === "high" ? "high" : "low",
221
+ reasoning: typeof i?.reasoning == "string" ? i.reasoning : void 0
222
222
  };
223
- } catch (i) {
224
- return console.warn("[PS-SDK:AgeCheck] error — failing open:", i), { isAdult: !0, confidence: "low" };
223
+ } catch (r) {
224
+ return console.warn("[PS-SDK:AgeCheck] error — failing open:", r), { isAdult: !0, confidence: "low" };
225
225
  }
226
226
  }
227
227
  const m = {};
@@ -629,7 +629,7 @@ const te = [
629
629
  "Your Weight": "체중",
630
630
  "Drag or scroll to set your height": "드래그 또는 스크롤하여 키를 설정하세요",
631
631
  "Drag or scroll to set your weight": "드래그 또는 스크롤하여 체중을 설정하세요"
632
- }, U = {
632
+ }, D = {
633
633
  "Virtual Try-On": "虚拟试穿",
634
634
  "Find Your Size & See It On You": "找到你的尺码并试穿",
635
635
  "Get the perfect fit, then try it on virtually": "找到最佳合身度,然后虚拟试穿",
@@ -746,7 +746,7 @@ const te = [
746
746
  "Your Weight": "你的体重",
747
747
  "Drag or scroll to set your height": "拖动或滚动设置身高",
748
748
  "Drag or scroll to set your weight": "拖动或滚动设置体重"
749
- }, D = {
749
+ }, U = {
750
750
  "Virtual Try-On": "Probador Virtual",
751
751
  "Find Your Size & See It On You": "Encuentra tu talla y pruébatelo",
752
752
  "Get the perfect fit, then try it on virtually": "Encuentra el ajuste perfecto y pruébatelo virtualmente",
@@ -2501,7 +2501,7 @@ const te = [
2501
2501
  "Your Weight": "น้ำหนักของคุณ",
2502
2502
  "Drag or scroll to set your height": "ลากหรือเลื่อนเพื่อตั้งค่าส่วนสูง",
2503
2503
  "Drag or scroll to set your weight": "ลากหรือเลื่อนเพื่อตั้งค่าน้ำหนัก"
2504
- }, x = {
2504
+ }, Z = {
2505
2505
  "Virtual Try-On": "Thử Đồ Ảo",
2506
2506
  "Find Your Size & See It On You": "Tìm cỡ của bạn và thử mặc",
2507
2507
  "Get the perfect fit, then try it on virtually": "Tìm size phù hợp nhất rồi thử mặc ảo",
@@ -2618,11 +2618,11 @@ const te = [
2618
2618
  "Your Weight": "Cân Nặng",
2619
2619
  "Drag or scroll to set your height": "Kéo hoặc cuộn để đặt chiều cao",
2620
2620
  "Drag or scroll to set your weight": "Kéo hoặc cuộn để đặt cân nặng"
2621
- }, Z = {
2621
+ }, x = {
2622
2622
  ja: I,
2623
2623
  ko: G,
2624
- zh: U,
2625
- es: D,
2624
+ zh: D,
2625
+ es: U,
2626
2626
  fr: w,
2627
2627
  de: H,
2628
2628
  it: C,
@@ -2637,9 +2637,9 @@ const te = [
2637
2637
  nb: j,
2638
2638
  fi: V,
2639
2639
  th: J,
2640
- vi: x
2640
+ vi: Z
2641
2641
  };
2642
- for (const [o, e] of Object.entries(Z))
2642
+ for (const [o, e] of Object.entries(x))
2643
2643
  N(o, e);
2644
2644
  export {
2645
2645
  q as A,
@@ -2655,4 +2655,4 @@ export {
2655
2655
  $ as i,
2656
2656
  N as r
2657
2657
  };
2658
- //# sourceMappingURL=index-Z44A-Ydq.js.map
2658
+ //# sourceMappingURL=index-YDYXhM8c.js.map