shopping-cli 3.2.1__tar.gz → 3.2.4__tar.gz
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.
- {shopping_cli-3.2.1/shopping_cli.egg-info → shopping_cli-3.2.4}/PKG-INFO +15 -1
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/README.md +14 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/pyproject.toml +1 -1
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/__init__.py +1 -1
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli.py +4 -2
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_adapter_commands.py +28 -3
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_common.py +10 -1
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/listings/projection.py +7 -20
- {shopping_cli-3.2.1 → shopping_cli-3.2.4/shopping_cli.egg-info}/PKG-INFO +15 -1
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/LICENSE +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/MANIFEST.in +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/setup.cfg +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/agents/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/agents/agent_cli.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/agents/buyer_cli.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/agents/merchant_agent.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/agents/merchant_daemon.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/agents/merchant_state_helpers.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/agents/tools.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/app.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/auth.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/error_handlers.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/error_response.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/fallback_asgi.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/fastapi_routes.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/agents.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/audit.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/buyer.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/catalog.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/common.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/conversations.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/erp.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/human_review.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/listings_projection.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/handlers/negotiation.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/idempotency.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/limits.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/request_dispatch.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/request_limits.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/route_matching.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/route_registry.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/route_table.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/routes_agents.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/routes_conversations.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/routes_marketplace.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/routes_merchants.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/api/server.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_agent_commands.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_buyer_commands.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_catalog_commands.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_conversation_commands.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_erp_commands.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/cli_listing_commands.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/commerce/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/commerce/adapters.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/commerce/data_source.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/config.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/contracts/kiwi-contracts.lock.json +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/contracts/shopping.negotiation/0.1/capabilities.schema.json +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/contracts/shopping.negotiation/0.1/decision.schema.json +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/contracts/shopping.negotiation/0.1/policy-result.schema.json +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/contracts/shopping.negotiation/0.1/snapshot.schema.json +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/catalog.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/catalog_scoring.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/catalog_text.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/catalog_views.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/channels.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/conversations.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/delivery.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/errors.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/harness.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/limits.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/negotiation.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/negotiation_contracts.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/policies.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/risk.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/core/tokens.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/data_sources/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/data_sources/adapter.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/data_sources/csv_excel_source.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/data_sources/erp_source.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/db/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/db/migrations.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/db/models.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/db/provenance.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/db/session.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/http_client.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/listings/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/__init__.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/agents.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/audit.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/buyer_bootstrap.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/conversations.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/human_review.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_gates.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_message.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_policy_helpers.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_policy_result.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_snapshot.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_snapshot_projection.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/tokens.py +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli.egg-info/SOURCES.txt +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli.egg-info/dependency_links.txt +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli.egg-info/entry_points.txt +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli.egg-info/requires.txt +0 -0
- {shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shopping-cli
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.4
|
|
4
4
|
Summary: Standalone local-commerce AI consultation marketplace runtime
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -310,6 +310,20 @@ printf 'longjing gift delivery today\n/summary\n/quit\n' | \
|
|
|
310
310
|
|
|
311
311
|
Default database path: `~/.local/share/shopping-cli/shopping-cli.sqlite`.
|
|
312
312
|
|
|
313
|
+
For a single-merchant deployment, import commands can read the database and
|
|
314
|
+
merchant identity from the environment instead of repeating tenant flags:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
export SHOPPING_DB_PATH="$HOME/.local/share/shopping-cli/shopping-cli.sqlite"
|
|
318
|
+
export SHOPPING_MERCHANT_ID="your-merchant-id"
|
|
319
|
+
|
|
320
|
+
shopping-cli import-csv-excel --file products.csv
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`KIWI_MERCHANT_ID` is accepted as a compatibility alias for
|
|
324
|
+
`SHOPPING_MERCHANT_ID`. Explicit `--db` and `--merchant` arguments take
|
|
325
|
+
precedence over environment variables.
|
|
326
|
+
|
|
313
327
|
## Channel Ingress
|
|
314
328
|
|
|
315
329
|
External channel adapters can ingest buyer messages through a stable local entry point before real WhatsApp, Telegram, Slack, or OpenClaw/Hermes gateway bridges are attached:
|
|
@@ -87,6 +87,20 @@ printf 'longjing gift delivery today\n/summary\n/quit\n' | \
|
|
|
87
87
|
|
|
88
88
|
Default database path: `~/.local/share/shopping-cli/shopping-cli.sqlite`.
|
|
89
89
|
|
|
90
|
+
For a single-merchant deployment, import commands can read the database and
|
|
91
|
+
merchant identity from the environment instead of repeating tenant flags:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
export SHOPPING_DB_PATH="$HOME/.local/share/shopping-cli/shopping-cli.sqlite"
|
|
95
|
+
export SHOPPING_MERCHANT_ID="your-merchant-id"
|
|
96
|
+
|
|
97
|
+
shopping-cli import-csv-excel --file products.csv
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`KIWI_MERCHANT_ID` is accepted as a compatibility alias for
|
|
101
|
+
`SHOPPING_MERCHANT_ID`. Explicit `--db` and `--merchant` arguments take
|
|
102
|
+
precedence over environment variables.
|
|
103
|
+
|
|
90
104
|
## Channel Ingress
|
|
91
105
|
|
|
92
106
|
External channel adapters can ingest buyer messages through a stable local entry point before real WhatsApp, Telegram, Slack, or OpenClaw/Hermes gateway bridges are attached:
|
|
@@ -866,8 +866,10 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
866
866
|
import_csv = subparsers.add_parser(
|
|
867
867
|
"import-csv-excel", help="Import product facts from CSV / Excel (.xlsx) into the local store"
|
|
868
868
|
)
|
|
869
|
-
import_csv.add_argument("--file",
|
|
870
|
-
import_csv.add_argument("--
|
|
869
|
+
import_csv.add_argument("--file", default="", help="Path to .csv / .tsv / .xlsx file (required unless --template)")
|
|
870
|
+
import_csv.add_argument("--template", default="", dest="template", help="写一份 CSV 模板到该路径后退出(不导入)")
|
|
871
|
+
import_csv.add_argument("--merchant", default="", dest="merchant", help="Owning merchant id (or SHOPPING_MERCHANT_ID / KIWI_MERCHANT_ID)")
|
|
872
|
+
import_csv.add_argument("--default-merchant", default="", dest="default_merchant", help=argparse.SUPPRESS)
|
|
871
873
|
import_csv.add_argument("--allowed-merchant", default="", dest="allowed_merchant", help="Tenant boundary: only rows of this merchant are written")
|
|
872
874
|
import_csv.add_argument("--format", choices=["text", "json"], default="text")
|
|
873
875
|
import_csv.set_defaults(func=cmd_import_csv_excel)
|
|
@@ -7,17 +7,25 @@
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import argparse
|
|
10
|
+
import os
|
|
10
11
|
|
|
11
12
|
from shopping_cli.cli_common import db_path_from_args, emit
|
|
12
13
|
from shopping_cli.data_sources import csv_excel_source # noqa: F401 # 导入即注册适配器
|
|
13
14
|
from shopping_cli.data_sources.adapter import (
|
|
14
|
-
AdapterError,
|
|
15
15
|
SyncContext,
|
|
16
16
|
registered_adapters,
|
|
17
17
|
run,
|
|
18
18
|
)
|
|
19
19
|
from shopping_cli.db.session import db_session
|
|
20
20
|
|
|
21
|
+
# CSV/Excel 导入模板(与 examples/products-template.csv 一致)。必填列 sku/title/
|
|
22
|
+
# price/stock;可选 currency(缺省 CNY)/ category / description / merchant_id。
|
|
23
|
+
PRODUCTS_TEMPLATE_CSV = (
|
|
24
|
+
"sku,title,price,stock,currency,category,description\n"
|
|
25
|
+
"VQ-001,智能保温杯 500ml,129.00,50,CNY,kitchenware,316 不锈钢内胆真空保温\n"
|
|
26
|
+
"VQ-002,桌面无线充电器 15W,89.00,120,CNY,electronics,兼容 QC3.0\n"
|
|
27
|
+
)
|
|
28
|
+
|
|
21
29
|
|
|
22
30
|
def cmd_adapters_list(args: argparse.Namespace) -> None:
|
|
23
31
|
"""列出已注册适配器(Adapter SDK 注册表)。"""
|
|
@@ -28,9 +36,26 @@ def cmd_adapters_list(args: argparse.Namespace) -> None:
|
|
|
28
36
|
|
|
29
37
|
|
|
30
38
|
def cmd_import_csv_excel(args: argparse.Namespace) -> None:
|
|
31
|
-
"""运行 CSV/Excel 适配器导入本地 products
|
|
39
|
+
"""运行 CSV/Excel 适配器导入本地 products 表;--template 只生成模板不导入。"""
|
|
40
|
+
template_path = str(getattr(args, "template", "") or "").strip()
|
|
41
|
+
if template_path:
|
|
42
|
+
with open(template_path, "w", encoding="utf-8", newline="") as fh:
|
|
43
|
+
fh.write(PRODUCTS_TEMPLATE_CSV)
|
|
44
|
+
emit(
|
|
45
|
+
{"ok": True, "message": f"CSV 模板已写入 {template_path}(填好 sku/title/price/stock 后再导入)"},
|
|
46
|
+
getattr(args, "format", "text"),
|
|
47
|
+
)
|
|
48
|
+
return
|
|
49
|
+
file_path = str(args.file or "").strip()
|
|
50
|
+
if not file_path:
|
|
51
|
+
raise SystemExit("--file <path> 必填(或先用 --template <path> 生成模板)")
|
|
32
52
|
db_path = db_path_from_args(args)
|
|
33
|
-
merchant_id =
|
|
53
|
+
merchant_id = (
|
|
54
|
+
str(args.merchant or "").strip()
|
|
55
|
+
or str(getattr(args, "default_merchant", "")).strip()
|
|
56
|
+
or str(os.environ.get("SHOPPING_MERCHANT_ID") or "").strip()
|
|
57
|
+
or str(os.environ.get("KIWI_MERCHANT_ID") or "").strip()
|
|
58
|
+
)
|
|
34
59
|
if not merchant_id:
|
|
35
60
|
raise SystemExit("--merchant is required (FK 归属防护)")
|
|
36
61
|
with db_session(db_path) as conn:
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import argparse
|
|
6
6
|
import json
|
|
7
7
|
import math
|
|
8
|
+
import os
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Any
|
|
10
11
|
|
|
@@ -132,4 +133,12 @@ def tcp_port(value: str) -> int:
|
|
|
132
133
|
|
|
133
134
|
|
|
134
135
|
def db_path_from_args(args: argparse.Namespace) -> Path:
|
|
135
|
-
|
|
136
|
+
configured = (
|
|
137
|
+
getattr(args, "agent_db", None)
|
|
138
|
+
or getattr(args, "db", None)
|
|
139
|
+
or getattr(args, "data", None)
|
|
140
|
+
or os.environ.get("SHOPPING_DB_PATH")
|
|
141
|
+
or os.environ.get("SHOPPING_DB")
|
|
142
|
+
or DEFAULT_DB_PATH
|
|
143
|
+
)
|
|
144
|
+
return Path(configured).expanduser()
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
"""PublicListingProjection(shopping-cli v0.3 §14/§16;DoD #1-#3)。
|
|
2
2
|
|
|
3
3
|
public-only 白名单投影:把 products 行压缩为可公开的 discovery projection。
|
|
4
|
-
**绝不输出** cost / floor price / 私密库存 / credentials / 客户特定条款
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
discovery hint(v0.3 §14)——权威值以本地 products 行为准(v3.0 起
|
|
9
|
-
发布面已随 kiwi-catalog 子系统迁移至独立服务)。
|
|
4
|
+
**绝不输出** cost / floor price / 私密库存 / credentials / 客户特定条款 / 价格 /
|
|
5
|
+
促销 / 底价(v0.3 §16 不得输出清单;DoD #2 有回归测试锁定)。商品 listing 只携带
|
|
6
|
+
名称 + 分类/标签/区域等发现元数据,价格与供应事实以本地 products 行为准
|
|
7
|
+
(v3.0 起发布面已随 kiwi-catalog 子系统迁移至独立服务)。
|
|
10
8
|
"""
|
|
11
9
|
|
|
12
10
|
from __future__ import annotations
|
|
@@ -27,11 +25,6 @@ def _now_iso() -> str:
|
|
|
27
25
|
return datetime.now(timezone.utc).isoformat()
|
|
28
26
|
|
|
29
27
|
|
|
30
|
-
def _hint_price_range(price: float, currency: str) -> str:
|
|
31
|
-
"""price_range_hint:粗粒度公开价格提示(不是报价)。"""
|
|
32
|
-
return f"{currency} {price:.0f}"
|
|
33
|
-
|
|
34
|
-
|
|
35
28
|
def _product_row(conn: sqlite3.Connection, sku: str) -> dict[str, Any]:
|
|
36
29
|
row = conn.execute(
|
|
37
30
|
"select * from products where sku = ?", (str(sku).strip(),)
|
|
@@ -74,12 +67,6 @@ def project_product_listing(
|
|
|
74
67
|
"category": str(row.get("category") or ""),
|
|
75
68
|
"regions": [],
|
|
76
69
|
"tags": json.loads(row.get("tags_json") or "[]"),
|
|
77
|
-
"commercial_hints": {
|
|
78
|
-
"price_range_hint": _hint_price_range(float(row["price"]), str(row.get("currency") or "CNY")),
|
|
79
|
-
"availability_hint": "in_stock" if int(row.get("stock", 0)) > 0 else "out_of_stock",
|
|
80
|
-
"moq": 1,
|
|
81
|
-
"supports_bulk_quote": True,
|
|
82
|
-
},
|
|
83
70
|
}
|
|
84
71
|
# 每商品成交入口(KTH destination_ref):商家自行维护,publish 时同步进
|
|
85
72
|
# catalog listing 的 handoff_destination_ref。审查 S-M3:私有字段,缺省
|
|
@@ -90,14 +77,14 @@ def project_product_listing(
|
|
|
90
77
|
if description:
|
|
91
78
|
projection["summary"] = description
|
|
92
79
|
|
|
93
|
-
# provenance
|
|
94
|
-
#
|
|
80
|
+
# provenance 标注:只存在于 projection(Merchant Kiwi 可见),发布前由
|
|
81
|
+
# strip_provenance 剥离;商品不再携带价格/库存 hint(名称-only,v0.3 §16)。
|
|
95
82
|
projection["_provenance"] = {
|
|
96
83
|
"authority": authority,
|
|
97
84
|
"source_revision": projection["source_revision"],
|
|
98
85
|
"observed_at": str(row.get("observed_at") or now),
|
|
99
86
|
"fresh_until": str(row.get("fresh_until") or ""),
|
|
100
|
-
"note": "discovery
|
|
87
|
+
"note": "name-only discovery projection; authoritative facts in the local product record",
|
|
101
88
|
}
|
|
102
89
|
return projection
|
|
103
90
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shopping-cli
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.4
|
|
4
4
|
Summary: Standalone local-commerce AI consultation marketplace runtime
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -310,6 +310,20 @@ printf 'longjing gift delivery today\n/summary\n/quit\n' | \
|
|
|
310
310
|
|
|
311
311
|
Default database path: `~/.local/share/shopping-cli/shopping-cli.sqlite`.
|
|
312
312
|
|
|
313
|
+
For a single-merchant deployment, import commands can read the database and
|
|
314
|
+
merchant identity from the environment instead of repeating tenant flags:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
export SHOPPING_DB_PATH="$HOME/.local/share/shopping-cli/shopping-cli.sqlite"
|
|
318
|
+
export SHOPPING_MERCHANT_ID="your-merchant-id"
|
|
319
|
+
|
|
320
|
+
shopping-cli import-csv-excel --file products.csv
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`KIWI_MERCHANT_ID` is accepted as a compatibility alias for
|
|
324
|
+
`SHOPPING_MERCHANT_ID`. Explicit `--db` and `--merchant` arguments take
|
|
325
|
+
precedence over environment variables.
|
|
326
|
+
|
|
313
327
|
## Channel Ingress
|
|
314
328
|
|
|
315
329
|
External channel adapters can ingest buyer messages through a stable local entry point before real WhatsApp, Telegram, Slack, or OpenClaw/Hermes gateway bridges are attached:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_policy_helpers.py
RENAMED
|
File without changes
|
{shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_policy_result.py
RENAMED
|
File without changes
|
|
File without changes
|
{shopping_cli-3.2.1 → shopping_cli-3.2.4}/shopping_cli/services/negotiation_snapshot_projection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|