@miravia_test/miravia-publish-skill 0.1.3 → 0.1.4

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/dist/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
@@ -249,7 +249,7 @@ PRD 中标记为新增 API,但当前 Miravia Open Platform 文档站点未上
249
249
 
250
250
  | Schema 字段(snake_case) | API 字段 / 位置 | 必填 | 说明 |
251
251
  |---|---|---|---|
252
- | `product_title` | `Attributes.name` | M | 商品标题,20~255 字符,≥5 个单词 |
252
+ | `product_title` | `Attributes.name` | M | 商品标题,20~205 字符,≥5 个单词 |
253
253
  | `product_images` | `Images.Image[]` | M | 主图列表,第 1 张为主图 |
254
254
  | `product_long_description` | `Attributes.description` | O | 长描述,可含简单 HTML |
255
255
  | `category_id` | `PrimaryCategory` | M | 叶子类目 ID |
@@ -16,7 +16,7 @@ FIELD_DEFINITIONS: Dict[str, Dict[str, str]] = {
16
16
  "mo": "Mandatory",
17
17
  "definition": "The title / name of the product.",
18
18
  "requirement": (
19
- "Length must be greater than 20 characters and less than 255 characters. "
19
+ "Length must be greater than 20 characters and less than 205 characters. "
20
20
  "Suggested format: Brand + category + collection/model + key features + using scenarios."
21
21
  ),
22
22
  },
@@ -375,7 +375,7 @@ FIELD_DEFINITIONS: Dict[str, Dict[str, str]] = {
375
375
 
376
376
  FIELD_GUIDES: Dict[str, Dict[str, str]] = {
377
377
  "en": {
378
- "product_title": "Product title (Mandatory): The title / name of the product. Must be 20-255 characters. Suggested format: Brand + category + collection/model + key features + using scenarios.",
378
+ "product_title": "Product title (Mandatory): The title / name of the product. Must be 20-205 characters. Suggested format: Brand + category + collection/model + key features + using scenarios.",
379
379
  "product_images": "Product images (Mandatory): Image URLs. The first image is the main image shown in search/home. First image must have white background, 1:1 aspect ratio, 330-5000px, <5MB, jpg/png/jpeg/webp. Max 8 images.",
380
380
  "product_long_description": "Product long description (Optional): May include simple HTML. 20-3000 characters; embedded HTML is not supported.",
381
381
  "category_id": "Category ID (Mandatory): The internal Miravia leaf category ID where the product will be listed.",
@@ -414,7 +414,7 @@ FIELD_GUIDES: Dict[str, Dict[str, str]] = {
414
414
  "selling_marketplace_aliexpress": "Selling marketplace - AliExpress (Optional): Selling status per country on the AliExpress platform.",
415
415
  },
416
416
  "zh": {
417
- "product_title": "商品标题(必填):商品的标题/名称。长度需大于 20 且小于 255 个字符。建议格式:品牌 + 类目 + 系列/型号 + 核心卖点 + 使用场景。",
417
+ "product_title": "商品标题(必填):商品的标题/名称。长度需大于 20 且小于 205 个字符。建议格式:品牌 + 类目 + 系列/型号 + 核心卖点 + 使用场景。",
418
418
  "product_images": "商品图片(必填):商品图片 URL。第一张图是在搜索/首页展示的主图,必须使用纯白背景、1:1 比例、330-5000px、<5MB,仅支持 jpg/png/jpeg/webp。最多 8 张。",
419
419
  "product_long_description": "商品长描述(选填):可包含简单 HTML 的长描述。长度 20-3000 字符;不支持嵌套复杂 HTML,建议使用列表、加粗、字体等简单标签。",
420
420
  "category_id": "类目 ID(必填):Miravia 叶子类目内部 ID,商品将挂靠在该类目下。",
@@ -240,12 +240,12 @@ class ProductClient:
240
240
  Returns:
241
241
  List of category candidates, each with category_id, name, confidence, etc.
242
242
  """
243
- body: Dict[str, Any] = {}
243
+ params: Dict[str, Any] = {}
244
244
  if title:
245
- body["title"] = title
245
+ params["title"] = title
246
246
  if image_urls:
247
- body["imageUrls"] = image_urls
248
- result = self.client.request("POST", "/product/category/recommend/get", body)
247
+ params["imageUrls"] = image_urls
248
+ result = self.client.request("GET", "/product/category/recommend/get", params)
249
249
  data = result.get("data", []) or []
250
250
  if isinstance(data, list):
251
251
  return data
@@ -156,10 +156,25 @@ class PublishModule:
156
156
  category_id = self.args.category_id
157
157
  product_name = self.args.product_name
158
158
  if not category_id:
159
- raise ValueError(i18n._("pub_create_requires_category"))
159
+ return {
160
+ "status": "need_category",
161
+ "message": i18n._("pub_create_requires_category"),
162
+ "next_actions": [i18n._("pub_ai_post_provide_category")],
163
+ }
160
164
  if not product_name:
161
- raise ValueError(i18n._("pub_create_requires_name"))
162
- _validate_title(product_name)
165
+ return {
166
+ "status": "title_invalid",
167
+ "message": i18n._("pub_create_requires_name"),
168
+ "next_actions": [i18n._("pub_ai_post_requires_source")],
169
+ }
170
+ title_err = validate_title(product_name)
171
+ if title_err:
172
+ return {
173
+ "status": "title_invalid",
174
+ "message": title_err,
175
+ "format_suggestion": i18n._("pub_title_format_suggestion"),
176
+ "next_actions": [i18n._("pub_ai_post_requires_source")],
177
+ }
163
178
 
164
179
  brand_resolution = self._resolve_brand_interactive()
165
180
  if brand_resolution.get("status") == "need_brand":
@@ -1095,7 +1110,11 @@ class PublishModule:
1095
1110
  "next_actions": [i18n._("pub_ai_post_requires_source")],
1096
1111
  }
1097
1112
  if not content_items:
1098
- raise ValueError(i18n._("pub_ai_post_no_content"))
1113
+ return {
1114
+ "status": "file_empty_or_corrupted",
1115
+ "message": i18n._("pub_file_empty_or_corrupted", source=sources[0] if sources else ""),
1116
+ "next_actions": [i18n._("pub_ai_post_requires_source")],
1117
+ }
1099
1118
 
1100
1119
  # Check for multiple products in Excel
1101
1120
  row_count = get_excel_row_count(content_items)
@@ -1738,7 +1757,7 @@ class PublishModule:
1738
1757
 
1739
1758
  package_dims = ("package_weight", "package_length", "package_width", "package_height")
1740
1759
  for idx, sku in enumerate(skus, start=1):
1741
- if not sku.get("SellerSku"):
1760
+ if not (sku.get("SellerSku") or sku.get("seller_sku")):
1742
1761
  missing.append(f"Seller SKU (SKU #{idx})")
1743
1762
  for dim in package_dims:
1744
1763
  val = sku.get(dim)
@@ -1809,7 +1828,7 @@ class PublishModule:
1809
1828
  if self._is_category_attribute_mandatory(category_attributes, "compliance_documents") and not schema.compliance_documents:
1810
1829
  missing.append("compliance_documents")
1811
1830
 
1812
- if not any(sku.get("SellerSku") for sku in skus):
1831
+ if not any(sku.get("SellerSku") or sku.get("seller_sku") for sku in skus):
1813
1832
  missing.append("seller_sku")
1814
1833
 
1815
1834
  return missing
@@ -2727,6 +2746,11 @@ class PublishModule:
2727
2746
  skus: List[Dict[str, Any]] = []
2728
2747
  for idx, sku in enumerate(data):
2729
2748
  processed = dict(sku)
2749
+ # Normalize seller_sku → SellerSku (accept both snake_case and PascalCase)
2750
+ if "seller_sku" in processed and "SellerSku" not in processed:
2751
+ processed["SellerSku"] = processed.pop("seller_sku")
2752
+ elif "seller_sku" in processed:
2753
+ processed.pop("seller_sku") # SellerSku already set
2730
2754
  if not processed.get("SellerSku"):
2731
2755
  raise ValueError(
2732
2756
  i18n._("pub_seller_sku_required", idx=idx + 1)
@@ -2904,7 +2928,7 @@ def _validate_create_payload(payload: Dict[str, Any]) -> None:
2904
2928
  raise ValueError(i18n._("pub_ean_duplicate_in_product"))
2905
2929
 
2906
2930
  # Check Seller SKU duplicate within same product
2907
- seller_skus = [sku.get("SellerSku") for sku in skus if sku.get("SellerSku")]
2931
+ seller_skus = [sku.get("SellerSku") or sku.get("seller_sku") for sku in skus if sku.get("SellerSku") or sku.get("seller_sku")]
2908
2932
  if len(seller_skus) != len(set(seller_skus)):
2909
2933
  raise ValueError(i18n._("pub_seller_sku_duplicate_in_product"))
2910
2934
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miravia_test/miravia-publish-skill",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Miravia Product Publish Skill installer — one command to install the Miravia AI product listing skill into any AI Agent (Qoder / Cursor / Claude Code). Upload materials and let the AI extract data and publish products automatically.",
5
5
  "bin": {
6
6
  "miravia-publish-skill": "bin/cli.js"