@seasonkoh/webaz 0.1.16 → 0.1.18
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/README.md +60 -5
- package/dist/layer0-foundation/L0-2-state-machine/engine.js +3 -0
- package/dist/layer1-agent/L1-1-mcp-server/server.js +899 -720
- package/dist/layer2-business/L2-8-feedback/build-feedback-engine.js +287 -0
- package/dist/layer2-business/L2-9-contribution/build-reputation-engine.js +102 -0
- package/dist/layer2-business/L2-9-contribution/build-tasks-engine.js +180 -0
- package/dist/layer3-trust/L3-1-dispute-engine/dispute-engine.js +16 -0
- package/dist/layer4-economics/L4-3-reputation/reputation-engine.js +1 -0
- package/dist/mcp.js +7 -3
- package/dist/pwa/data/onboarding-cases.js +345 -0
- package/dist/pwa/data/onboarding-quiz.js +247 -0
- package/dist/pwa/public/app.js +1459 -96
- package/dist/pwa/public/i18n.js +303 -2
- package/dist/pwa/public/icon-192.png +0 -0
- package/dist/pwa/public/icon-512.png +0 -0
- package/dist/pwa/public/manifest.json +5 -2
- package/dist/pwa/public/openapi.json +1 -1
- package/dist/pwa/public/sw.js +1 -1
- package/dist/pwa/routes/admin-protocol-params.js +80 -2
- package/dist/pwa/routes/admin-reports.js +14 -9
- package/dist/pwa/routes/auth-read.js +3 -1
- package/dist/pwa/routes/build-feedback.js +82 -0
- package/dist/pwa/routes/build-reputation.js +10 -0
- package/dist/pwa/routes/build-tasks.js +73 -0
- package/dist/pwa/routes/disputes-write.js +149 -1
- package/dist/pwa/routes/governance-auto-deactivate.js +108 -0
- package/dist/pwa/routes/governance-onboarding.js +785 -0
- package/dist/pwa/routes/leaderboard.js +10 -2
- package/dist/pwa/routes/orders-action.js +5 -1
- package/dist/pwa/routes/products-meta.js +30 -0
- package/dist/pwa/routes/profile-identity.js +1 -1
- package/dist/pwa/routes/public-utils.js +44 -0
- package/dist/pwa/routes/rewards-apply.js +210 -0
- package/dist/pwa/routes/rewards-auto-downgrade.js +65 -0
- package/dist/pwa/routes/rewards-escrow-expire.js +48 -0
- package/dist/pwa/routes/wallet-write.js +17 -31
- package/dist/pwa/routes/webauthn.js +1 -1
- package/dist/pwa/server.js +641 -64
- package/package.json +6 -3
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* webaz_update_order L1-6 更新订单状态(发货/揽收/投递/确认/争议)
|
|
12
12
|
* webaz_get_status L1-4 查询订单状态和历史
|
|
13
13
|
* webaz_wallet 查看钱包余额
|
|
14
|
+
* …(39 工具,完整定义见下方 TOOLS 数组;数量以 TOOLS.length 为准)
|
|
15
|
+
*
|
|
16
|
+
* 双模(RFC-003):NETWORK(WEBAZ_API_KEY → 调 webaz.xyz)/ SANDBOX(本机库);见 NETWORK_TOOLS / apiCall / toolBackend。
|
|
17
|
+
* 关联 / Related: AGENTS.md · RFC-003(双模) · RFC-004(webaz_feedback) · 元规则 #4 不撒谎(_mode 戳) /
|
|
18
|
+
* #6 不滥用(agent 责任制 + Iron-Rule 真人动作)· 生产端点在 src/pwa(NETWORK 共用)
|
|
14
19
|
*/
|
|
15
20
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
16
21
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -30,6 +35,87 @@ const TELEMETRY_URL = process.env.WEBAZ_TELEMETRY_URL ?? 'https://webaz.xyz/api/
|
|
|
30
35
|
// 2026-06-01: phase A pre-launch 默认 OFF(opt-in)— W8 public launch 时翻回 default ON + 加 README 披露段
|
|
31
36
|
// Phase A pre-launch: telemetry default OFF (opt-in). Flip to default ON at W8 launch + add README disclosure section.
|
|
32
37
|
const TELEMETRY_ENABLED = (process.env.WEBAZ_TELEMETRY ?? 'off').toLowerCase() === 'on';
|
|
38
|
+
// ─── RFC-003 P0: 双模(NETWORK / SANDBOX)骨架 ─────────────────────
|
|
39
|
+
// NETWORK = 带 api_key 调 webaz.xyz/api(加入共享生产网络);SANDBOX = 本地 SQLite(离线试玩,与全网隔离)。
|
|
40
|
+
// P0 不迁移任何工具(NETWORK_TOOLS 为空)→ 一切仍走本地 = 零行为变化;P1/P2 逐个把工具名加入集合切到网络。
|
|
41
|
+
const WEBAZ_API_URL = (process.env.WEBAZ_API_URL ?? 'https://webaz.xyz').replace(/\/+$/, '');
|
|
42
|
+
const WEBAZ_API_KEY = process.env.WEBAZ_API_KEY ?? '';
|
|
43
|
+
const WEBAZ_MODE_ENV = (process.env.WEBAZ_MODE ?? '').toLowerCase();
|
|
44
|
+
// 模式:显式 WEBAZ_MODE 优先;否则有 api_key → network,无 → sandbox
|
|
45
|
+
const MODE = WEBAZ_MODE_ENV === 'network' ? 'network'
|
|
46
|
+
: WEBAZ_MODE_ENV === 'sandbox' ? 'sandbox'
|
|
47
|
+
: (WEBAZ_API_KEY ? 'network' : 'sandbox');
|
|
48
|
+
// 已迁移到 NETWORK 的工具名。P1/P2 逐个加入;未在集合里的工具仍走 sandbox(本地)。
|
|
49
|
+
// P1(读工具): 纯公开读,无写无 Passkey,作"MCP 连得上生产网络"的首验证。
|
|
50
|
+
const NETWORK_TOOLS = new Set([
|
|
51
|
+
'webaz_price_history',
|
|
52
|
+
'webaz_leaderboard',
|
|
53
|
+
'webaz_verify_price',
|
|
54
|
+
'webaz_place_order',
|
|
55
|
+
'webaz_list_product',
|
|
56
|
+
'webaz_update_order',
|
|
57
|
+
'webaz_search',
|
|
58
|
+
'webaz_get_status',
|
|
59
|
+
'webaz_feedback',
|
|
60
|
+
'webaz_contribute',
|
|
61
|
+
]);
|
|
62
|
+
const recentCalls = [];
|
|
63
|
+
function pushRecentCall(c) {
|
|
64
|
+
recentCalls.push(c);
|
|
65
|
+
if (recentCalls.length > 8)
|
|
66
|
+
recentCalls.shift(); // 只留最近 8 条
|
|
67
|
+
}
|
|
68
|
+
// 单个工具实际后端:仅当全局 network 且该工具已迁移,才走网络;否则 sandbox。
|
|
69
|
+
function toolBackend(tool) {
|
|
70
|
+
return (MODE === 'network' && NETWORK_TOOLS.has(tool)) ? 'network' : 'sandbox';
|
|
71
|
+
}
|
|
72
|
+
// 统一 API helper(P1/P2 迁移工具时使用)。Bearer api_key + 15s 超时 + 错误映射。
|
|
73
|
+
async function apiCall(path, opts = {}) {
|
|
74
|
+
const { method = 'GET', body } = opts;
|
|
75
|
+
const key = opts.apiKey || WEBAZ_API_KEY; // 每次调用可覆盖(工具 args.api_key 优先);否则用全局配置 key
|
|
76
|
+
const url = WEBAZ_API_URL + (path.startsWith('/') ? path : '/' + path);
|
|
77
|
+
try {
|
|
78
|
+
const resp = await fetch(url, {
|
|
79
|
+
method,
|
|
80
|
+
headers: {
|
|
81
|
+
...(key ? { authorization: `Bearer ${key}` } : {}),
|
|
82
|
+
...(body != null ? { 'content-type': 'application/json' } : {}),
|
|
83
|
+
},
|
|
84
|
+
...(body != null ? { body: JSON.stringify(body) } : {}),
|
|
85
|
+
signal: AbortSignal.timeout(15_000),
|
|
86
|
+
});
|
|
87
|
+
let json = null;
|
|
88
|
+
try {
|
|
89
|
+
json = await resp.json();
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
json = null;
|
|
93
|
+
}
|
|
94
|
+
if (!resp.ok) {
|
|
95
|
+
const map = {
|
|
96
|
+
401: 'api_key 无效或未注册 — 请在 https://webaz.xyz 注册并把 api_key 填入 WEBAZ_API_KEY',
|
|
97
|
+
403: '权限不足 / 需邀请码 / 该动作需真人 Passkey(请到 webaz.xyz 用 Passkey 操作)',
|
|
98
|
+
429: '调用过于频繁,请稍后再试',
|
|
99
|
+
503: '服务暂不可用,请稍后重试',
|
|
100
|
+
};
|
|
101
|
+
return { error: json?.error ?? map[resp.status] ?? `HTTP ${resp.status}`, error_code: json?.error_code, http_status: resp.status };
|
|
102
|
+
}
|
|
103
|
+
return json ?? {};
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
const msg = e.name === 'TimeoutError' ? '请求超时(15s)' : e.message;
|
|
107
|
+
return { error: `网络错误:${msg}`, network_error: true };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// 启动 banner(stderr)+ status 声明用 —— 让用户/agent 一眼知道现在是真网络还是沙盒
|
|
111
|
+
function modeBanner() {
|
|
112
|
+
if (MODE === 'network') {
|
|
113
|
+
return `🟢 NETWORK mode — webaz.xyz (${WEBAZ_API_URL}). Migrated tools: ${NETWORK_TOOLS.size}/${TOOLS.length}`
|
|
114
|
+
+ (NETWORK_TOOLS.size === 0 ? ' ⚠️ network client not active yet (P0 scaffold) — all tools still SANDBOX/local.' : '');
|
|
115
|
+
}
|
|
116
|
+
return `🟡 SANDBOX mode — local-only (~/.webaz/webaz.db), NOT the live network. Data is private to this machine.`
|
|
117
|
+
+ (WEBAZ_API_KEY ? '' : ' Set WEBAZ_API_KEY (register at webaz.xyz) to join the network.');
|
|
118
|
+
}
|
|
33
119
|
// ─── 初始化 ──────────────────────────────────────────────────
|
|
34
120
|
const db = initDatabase();
|
|
35
121
|
initSystemUser(db);
|
|
@@ -156,10 +242,7 @@ const TOOLS = [
|
|
|
156
242
|
Returns: protocol overview, available tools, role responsibilities, operation flows, **network_state (pre-launch disclaimer)**, **commission_model.compliance_notice (MLM-form disclosure)**.
|
|
157
243
|
No auth required, no parameters needed.
|
|
158
244
|
|
|
159
|
-
⚠️ Important: WebAZ is currently **pre-launch** with ~0 real users on the canonical endpoint. All stats / counts returned by this and other tools come from the **local MCP SQLite DB**, not protocol-wide prod state. Read network_state field BEFORE you treat any number as real-economy data
|
|
160
|
-
|
|
161
|
-
──
|
|
162
|
-
中文:获取 WebAZ 说明 — 新 Agent 接入协议时应首先调用,返回协议简介、可用工具、角色职责、**网络状态(pre-launch 披露)** + **佣金结构合规提示(MLM 形态披露)**。⚠️ 协议尚未上线,统计来自本地库,不是真实运营数据。`,
|
|
245
|
+
⚠️ Important: WebAZ is currently **pre-launch** with ~0 real users on the canonical endpoint. All stats / counts returned by this and other tools come from the **local MCP SQLite DB**, not protocol-wide prod state. Read network_state field BEFORE you treat any number as real-economy data.`,
|
|
163
246
|
inputSchema: {
|
|
164
247
|
type: 'object',
|
|
165
248
|
properties: {},
|
|
@@ -167,46 +250,31 @@ No auth required, no parameters needed.
|
|
|
167
250
|
},
|
|
168
251
|
{
|
|
169
252
|
name: 'webaz_register',
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
- permanent_code (6-char recovery code — use with handle via webaz_mykey to recover lost api_key)
|
|
173
|
-
- handle (URL-safe unique ID derived from name; if requested handle is taken, system auto-appends numeric suffix — check handle_modified flag)
|
|
174
|
-
- created_at (ISO timestamp)
|
|
175
|
-
|
|
176
|
-
⚠️ Consent required: WebAZ is pre-launch and contains a 3-tier commission + binary PV pairing structure (see webaz_info.commission_model.compliance_notice — may overlap with MLM legal definitions). An agent acting for a human user MUST get the user's explicit, informed consent BEFORE creating an account on their behalf. Do NOT auto-register users just because they asked a generic shopping question.
|
|
253
|
+
// was ~1732 chars, now ~780 chars
|
|
254
|
+
description: `Register a new WebAZ account. Returns: api_key (36-char 128-bit credential, store securely) + permanent_code (6-char recovery code, pair with handle in webaz_mykey to recover lost api_key) + handle (URL-safe ID; if taken, system appends numeric suffix — check handle_modified flag) + created_at.
|
|
177
255
|
|
|
178
|
-
|
|
179
|
-
- buyer: browse, order, confirm receipt
|
|
180
|
-
- seller: list products, accept orders, ship
|
|
181
|
-
- logistics: pickup, transit updates, delivery confirm
|
|
182
|
-
- reviewer: structured product reviews
|
|
183
|
-
- arbitrator: handle disputes, issue rulings
|
|
256
|
+
⚠️ **Consent required (MLM disclosure)**: WebAZ is pre-launch with 3-tier commission + binary PV pairing structure (may overlap with MLM legal definitions; see webaz_info.commission_model.compliance_notice). Agent acting on behalf of human user **MUST get explicit informed consent BEFORE creating account**. Do NOT auto-register from generic shopping questions.
|
|
184
257
|
|
|
185
|
-
|
|
186
|
-
- Does NOT set placement_id / sponsor_id (binary tree + referral chain not built) — MCP registration does NOT enroll the user into the multi-tier structure
|
|
187
|
-
- To build a referral chain: user must arrive via webaz_share_link ?ref=<uid> URL clicked in browser (PWA flow) — explicit user action required
|
|
188
|
-
- region defaults to 'global' if omitted; valid: singapore, china, usa, malaysia, indonesia, thailand, vietnam, taiwan, hk, global
|
|
258
|
+
Roles: buyer (browse/order/confirm) | seller (list/accept/ship) | logistics (pickup/transit/deliver) | reviewer (reviews) | arbitrator (disputes/rulings).
|
|
189
259
|
|
|
190
|
-
|
|
191
|
-
中文:注册 WebAZ 账户。返回 api_key(128-bit 凭证)+ permanent_code(恢复码)+ handle(唯一标识,冲突自动加后缀,看 handle_modified)+ created_at。可选角色:买家/卖家/物流/测评员/仲裁员。
|
|
192
|
-
注意:MCP register 不建立 placement/sponsor 链(防 bot),需要建链时用 webaz_share_link + PWA 浏览器注册。`,
|
|
260
|
+
⚠️ **MCP register limitations (anti-bot, by design)**: does NOT set placement_id/sponsor_id — referral/PV chain NOT built via MCP. To build chain: user must arrive via webaz_share_link \`?ref=<uid>\` URL clicked in browser (PWA flow). region defaults 'global'; valid: singapore/china/usa/malaysia/indonesia/thailand/vietnam/taiwan/hk/global.`,
|
|
193
261
|
inputSchema: {
|
|
194
262
|
type: 'object',
|
|
195
263
|
properties: {
|
|
196
|
-
name: { type: 'string', description: '
|
|
264
|
+
name: { type: 'string', description: 'Your name or shop name' },
|
|
197
265
|
role: {
|
|
198
266
|
type: 'string',
|
|
199
267
|
enum: ['buyer', 'seller', 'logistics', 'reviewer', 'arbitrator'],
|
|
200
|
-
description: '
|
|
268
|
+
description: 'Your role in the protocol',
|
|
201
269
|
},
|
|
202
270
|
initial_balance: {
|
|
203
271
|
type: 'number',
|
|
204
|
-
description: '
|
|
272
|
+
description: 'Initial mock balance (for testing, default 1000 WAZ)',
|
|
205
273
|
},
|
|
206
274
|
region: {
|
|
207
275
|
type: 'string',
|
|
208
276
|
enum: ['global', 'singapore', 'china', 'usa', 'malaysia', 'indonesia', 'thailand', 'vietnam', 'taiwan', 'hk'],
|
|
209
|
-
description: '
|
|
277
|
+
description: 'Account region (default global; affects referral region cap + commission redirect_region_cap rules)',
|
|
210
278
|
},
|
|
211
279
|
},
|
|
212
280
|
required: ['name', 'role'],
|
|
@@ -214,184 +282,133 @@ Roles:
|
|
|
214
282
|
},
|
|
215
283
|
{
|
|
216
284
|
name: 'webaz_search',
|
|
285
|
+
// was ~2607 chars, now ~1050 chars
|
|
217
286
|
description: `Search WebAZ marketplace + cross-platform anchor lookup. No auth required.
|
|
218
287
|
|
|
219
|
-
⚠️ **STRICT MATCH ONLY**
|
|
220
|
-
不做 fuzzy LIKE 模糊降级。短查询(如 "钱包" "iphone")很大概率 0 命中,这是设计如此,不是 bug。
|
|
221
|
-
0 命中时,**不要**自己拼短词 retry,也**不要**调别的工具假装搜索;应**引导用户访问 https://webaz.xyz/#discover**
|
|
222
|
-
在搜索框输入关键词浏览(那里有 fuzzy LIKE)。模糊搜索是用户主动行为,不是 agent 代办。
|
|
288
|
+
⚠️ **STRICT MATCH ONLY** (no fuzzy fallback). query matches = exact title OR exact external_title OR alias ≥6 chars contained in user text. Short queries (e.g. "iphone") likely return 0 — **this is by design, NOT a bug**. On 0 results: do NOT retry with shorter terms, do NOT call other tools to fake search. Direct user to https://webaz.xyz/#discover for fuzzy browse (user action, not agent's job).
|
|
223
289
|
|
|
224
290
|
USE THIS when:
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
→ WebAZ exact-matches against its anchor registry
|
|
229
|
-
platforms). matched_by='none' means truly not indexed — do NOT silently fall back to keyword,
|
|
230
|
-
and do NOT guess similar products.
|
|
231
|
-
|
|
232
|
-
⚠️ Do not skip this tool just because user gave you a URL — URL-paste is a first-class mode here,
|
|
233
|
-
NOT a separate browser-fetch capability. Returns structured specs + logistics + after-sales +
|
|
234
|
-
agent_summary (one-line decision hint).
|
|
291
|
+
- User gives **full product title / SKU / precise description** (strict-match candidate), OR
|
|
292
|
+
- User gives **filters** (category / max_price / min_return_days / max_handling_hours / sort), OR
|
|
293
|
+
- User pastes **external URL / share-text** from Taobao / Tmall / JD / PDD / 1688 / Douyin / Xiaohongshu
|
|
294
|
+
→ URL-paste is a first-class mode of THIS tool, NOT a separate browser-fetch. WebAZ exact-matches against its cross-platform anchor registry.
|
|
235
295
|
|
|
236
|
-
【
|
|
237
|
-
query 命中 = (1) 完全等于 product.title OR (2) 完全等于任一 external_title OR (3) 用户文本包含任一卖家声明 alias_value (≥6 字符)。模糊关键词请引导用户去 PWA #discover。
|
|
296
|
+
【External-link paste】Prefer LLM-parse into \`external_link\` { platform, external_id?, external_title } (title = verbatim text inside 「」). If unparseable, drop raw into \`paste_text\` (server does light regex). Match: L1 external_id exact → L2 external_title exact → else \`matched_by:'none'\`. **No fuzzy fallback, no keyword degradation, no similar-product guessing.** matched_by='none' = tell user honestly "no exact match"; trust premise is precise not "looks similar".
|
|
238
297
|
|
|
239
|
-
|
|
240
|
-
(e.g. '【淘宝】「Product Name」 https://e.tb.cn/xxx ...'), do:
|
|
241
|
-
1) Prefer your own LLM parsing → pass external_link object with:
|
|
242
|
-
- platform: 'taobao'|'tmall'|'jd'|'pdd'|'1688'|'douyin'|'xhs'
|
|
243
|
-
- external_id: canonical product ID (if resolvable from short URL; else omit)
|
|
244
|
-
- external_title: the title text inside 「」 brackets verbatim
|
|
245
|
-
2) If you can't parse, drop the raw text into paste_text — WebAZ server does light regex parsing (no outbound calls)
|
|
246
|
-
|
|
247
|
-
Match rules (STRICT, no guessing):
|
|
248
|
-
- Level 1: external_id exact match
|
|
249
|
-
- Level 2: external_title string exact match
|
|
250
|
-
- Neither hit → matched_by: 'none', **NO fuzzy fallback, NO keyword degradation**
|
|
251
|
-
|
|
252
|
-
IMPORTANT: matched_by='none' is an honest signal — tell the user "no exact match found".
|
|
253
|
-
Do NOT silently fall back to keyword search (that's a separate tool's job).
|
|
254
|
-
Do NOT guess similar products from title impressions.
|
|
255
|
-
WebAZ's trust premise is that match results are TRULY precise, not "looks similar".
|
|
256
|
-
|
|
257
|
-
Note: paste-link matching hits webaz.xyz production data, not your local webaz.db.
|
|
258
|
-
|
|
259
|
-
──
|
|
260
|
-
中文:商品搜索(无需登录)。两种模式:关键词搜索 + 粘贴外链精准匹配。外链匹配强制精准(仅 external_id 或 external_title 完全相等命中),不命中返回 matched_by:'none',不做模糊降级。`,
|
|
298
|
+
Returns: structured specs + logistics + after-sales + agent_summary (one-line decision hint). Paste-link hits webaz.xyz prod data, not local webaz.db.`,
|
|
261
299
|
inputSchema: {
|
|
262
300
|
type: 'object',
|
|
263
301
|
properties: {
|
|
264
|
-
query: { type: 'string', description: '
|
|
265
|
-
category: { type: 'string', description: '
|
|
266
|
-
max_price: { type: 'number', description: '
|
|
267
|
-
min_return_days: { type: 'number', description: '
|
|
268
|
-
max_handling_hours: { type: 'number', description: '
|
|
269
|
-
paste_text: { type: 'string', description: '
|
|
302
|
+
query: { type: 'string', description: 'Search keyword (product name or description)' },
|
|
303
|
+
category: { type: 'string', description: 'Category filter (optional)' },
|
|
304
|
+
max_price: { type: 'number', description: 'Max price filter (optional)' },
|
|
305
|
+
min_return_days: { type: 'number', description: 'Min return days (optional, e.g. 7 = only ≥7-day return)' },
|
|
306
|
+
max_handling_hours: { type: 'number', description: 'Max handling hours (optional, e.g. 24 = only ≤24h dispatch)' },
|
|
307
|
+
paste_text: { type: 'string', description: 'Raw paste text / external link (optional; server does light regex parse)' },
|
|
270
308
|
external_link: {
|
|
271
309
|
type: 'object',
|
|
272
|
-
description: '
|
|
310
|
+
description: 'Structured external link match (optional, agent-parsed)',
|
|
273
311
|
properties: {
|
|
274
312
|
platform: { type: 'string', description: "'taobao'|'tmall'|'jd'|'pdd'|'1688'|'douyin'|'xhs'" },
|
|
275
|
-
external_id: { type: 'string', description: '
|
|
276
|
-
external_title: { type: 'string', description: '
|
|
277
|
-
canonical_url: { type: 'string', description: '
|
|
313
|
+
external_id: { type: 'string', description: 'Platform product canonical ID (optional)' },
|
|
314
|
+
external_title: { type: 'string', description: 'Platform product title verbatim (optional)' },
|
|
315
|
+
canonical_url: { type: 'string', description: 'Canonical URL (optional)' },
|
|
278
316
|
},
|
|
279
317
|
},
|
|
280
|
-
limit: { type: 'number', description: '
|
|
281
|
-
sort: { type: 'string', enum: ['trending', 'newest', 'rating', 'price_asc', 'price_desc', 'random'], description: '
|
|
282
|
-
has_sales: { type: 'string', enum: ['true', 'false'], description: 'true
|
|
283
|
-
ship_to: { type: 'string', description: '
|
|
284
|
-
seller_id: { type: 'string', description: '
|
|
285
|
-
cursor: { type: 'string', description: '
|
|
318
|
+
limit: { type: 'number', description: 'Result limit, default 10; agent mode up to 200' },
|
|
319
|
+
sort: { type: 'string', enum: ['trending', 'newest', 'rating', 'price_asc', 'price_desc', 'random'], description: 'Sort: trending=composite (default) / newest / rating / price_asc / price_desc / random' },
|
|
320
|
+
has_sales: { type: 'string', enum: ['true', 'false'], description: 'true=only sold; false=only new' },
|
|
321
|
+
ship_to: { type: 'string', description: 'Ship-to (province/city); auto-filters unshippable' },
|
|
322
|
+
seller_id: { type: 'string', description: 'Filter to one seller' },
|
|
323
|
+
cursor: { type: 'string', description: 'Pagination cursor (from previous next_cursor)' },
|
|
286
324
|
},
|
|
287
325
|
},
|
|
288
326
|
},
|
|
289
327
|
{
|
|
290
328
|
name: 'webaz_verify_price',
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
USE THIS for EVERY purchase, not just price-sensitive ones. Reasons:
|
|
294
|
-
(1) order price matches displayed (defeats flash-sale / hidden-fee races)
|
|
295
|
-
(2) caller is alerted if price changed between view and order
|
|
296
|
-
(3) protocol only liable for T0 price
|
|
297
|
-
(4) reduces stock-depletion race on hot items (session_token is single-use within 10min)
|
|
329
|
+
// was ~647 chars, now ~370 chars
|
|
330
|
+
description: `Lock price + reserve stock BEFORE webaz_place_order — returns \`session_token\` (10-min TTL, single-use, pass to place_order).
|
|
298
331
|
|
|
299
|
-
|
|
332
|
+
USE THIS for **EVERY purchase**: (1) defeats flash-sale / hidden-fee race (2) alerts if price drifted (3) protocol only liable for T0 price (4) reduces stock-depletion race on hot items.
|
|
300
333
|
|
|
301
|
-
|
|
302
|
-
中文:下单前锁价 — 10 分钟一次性 session_token;agent 应先调此再调 place_order。`,
|
|
334
|
+
Skipping is allowed but agent then carries price/stock-race risk itself.`,
|
|
303
335
|
inputSchema: {
|
|
304
336
|
type: 'object',
|
|
305
337
|
properties: {
|
|
306
|
-
api_key: { type: 'string', description: '
|
|
307
|
-
product_id: { type: 'string', description: '
|
|
308
|
-
quantity: { type: 'number', description: '
|
|
338
|
+
api_key: { type: 'string', description: "Buyer's api_key" },
|
|
339
|
+
product_id: { type: 'string', description: 'Product ID (from webaz_search)' },
|
|
340
|
+
quantity: { type: 'number', description: 'Quantity, default 1' },
|
|
309
341
|
},
|
|
310
342
|
required: ['api_key', 'product_id'],
|
|
311
343
|
},
|
|
312
344
|
},
|
|
313
345
|
{
|
|
314
346
|
name: 'webaz_list_product',
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
USE THIS when SELLER wants to:
|
|
318
|
-
- publish a NEW product to their catalog, OR
|
|
319
|
-
- update / delist / relist / trash / delete an existing product they own, OR
|
|
320
|
-
- view their OWN listings (action=mine)
|
|
347
|
+
// was ~1336 chars, now ~650 chars
|
|
348
|
+
description: `⚠️ **"list" = PUBLISH** (verb), NOT "list out". Seller-only catalog publish + manage.
|
|
321
349
|
|
|
322
|
-
NOT for browsing
|
|
350
|
+
USE THIS when seller wants to publish / update / delist / relist / trash / delete own product, OR view own listings (action=mine). NOT for browsing marketplace — use webaz_search (anyone, no auth). Requires seller api_key. On create: system auto-suggests stake ~15% of price (buyer protection).
|
|
323
351
|
|
|
324
|
-
Fill fields completely —
|
|
325
|
-
Note: for "exclusive price vs external link" listing, use PWA Web only — link claim needs crowd-verification.
|
|
352
|
+
Fill agent_summary fields completely (brand/return/handling/warranty) — helps buyer agents compare. For "exclusive-price vs external-link" listing → PWA Web only (link claim needs crowd-verify).
|
|
326
353
|
|
|
327
|
-
Actions:
|
|
328
|
-
- create list a new product (default; needs title/description/price)
|
|
329
|
-
- mine list all my products (no product_id needed)
|
|
330
|
-
- update modify fields (needs product_id; only changed fields)
|
|
331
|
-
- delist move to warehouse (status: warehouse; needs product_id)
|
|
332
|
-
- relist re-shelve from warehouse (status: active; needs product_id)
|
|
333
|
-
- trash move to trash (status: deleted; needs product_id)
|
|
334
|
-
- delete permanent delete (only trash items with no active orders; needs product_id)
|
|
335
|
-
|
|
336
|
-
──
|
|
337
|
-
中文:卖家商品目录管理(上架/更新/下架/回收/删除/查询)。Actions: create / mine / update / delist / relist / trash / delete。上架时系统自动建议 15% 价格的质押金。`,
|
|
354
|
+
Actions: create (title/description/price) | mine | update (product_id + changed fields) | delist (→ warehouse) | relist (warehouse → active) | trash (→ deleted) | delete (only trash, no active orders).`,
|
|
338
355
|
inputSchema: {
|
|
339
356
|
type: 'object',
|
|
340
357
|
properties: {
|
|
341
|
-
api_key: { type: 'string', description: '
|
|
358
|
+
api_key: { type: 'string', description: "Seller's api_key" },
|
|
342
359
|
action: {
|
|
343
360
|
type: 'string',
|
|
344
361
|
enum: ['create', 'mine', 'update', 'delist', 'relist', 'trash', 'delete'],
|
|
345
|
-
description: '
|
|
362
|
+
description: 'Action (default: create)',
|
|
346
363
|
},
|
|
347
|
-
product_id: { type: 'string', description: '
|
|
348
|
-
title: { type: 'string', description: '
|
|
349
|
-
description: { type: 'string', description: '
|
|
350
|
-
price: { type: 'number', description: '
|
|
351
|
-
stock: { type: 'number', description: '
|
|
352
|
-
category: { type: 'string', description: '
|
|
364
|
+
product_id: { type: 'string', description: 'Product ID (required for update/delist/relist/trash/delete)' },
|
|
365
|
+
title: { type: 'string', description: 'Product name (required for create; optional for update)' },
|
|
366
|
+
description: { type: 'string', description: 'Product description (required for create; optional for update)' },
|
|
367
|
+
price: { type: 'number', description: 'Price in WAZ (required for create; optional for update)' },
|
|
368
|
+
stock: { type: 'number', description: 'Stock, default 1' },
|
|
369
|
+
category: { type: 'string', description: 'Category (optional)' },
|
|
353
370
|
specs: {
|
|
354
371
|
type: 'object',
|
|
355
|
-
description: '
|
|
372
|
+
description: 'Structured specs k/v, e.g. {"color":"black","ram":"16GB","storage":"512GB"} (optional)',
|
|
356
373
|
},
|
|
357
|
-
brand: { type: 'string', description: '
|
|
358
|
-
model: { type: 'string', description: '
|
|
374
|
+
brand: { type: 'string', description: 'Brand (optional)' },
|
|
375
|
+
model: { type: 'string', description: 'Model (optional)' },
|
|
359
376
|
source_price: {
|
|
360
377
|
type: 'number',
|
|
361
|
-
description: '
|
|
378
|
+
description: 'External reference price (optional, display only; exclusive-price auth needs PWA link-claim)',
|
|
362
379
|
},
|
|
363
|
-
ship_regions: { type: 'string', description: '
|
|
364
|
-
handling_hours: { type: 'number', description: '
|
|
380
|
+
ship_regions: { type: 'string', description: 'Ship region, default "all"' },
|
|
381
|
+
handling_hours: { type: 'number', description: 'Handling time (hours), default 24' },
|
|
365
382
|
estimated_days: {
|
|
366
383
|
type: 'object',
|
|
367
|
-
description: '
|
|
384
|
+
description: 'Estimated delivery days: number (e.g. 4) OR region map (e.g. {"east":2,"all":4})',
|
|
368
385
|
},
|
|
369
|
-
fragile: { type: 'boolean', description: '
|
|
370
|
-
return_days: { type: 'number', description: '
|
|
371
|
-
return_condition: { type: 'string', description: '
|
|
372
|
-
warranty_days: { type: 'number', description: '
|
|
386
|
+
fragile: { type: 'boolean', description: 'Fragile flag, default false' },
|
|
387
|
+
return_days: { type: 'number', description: 'Return days, default 7 (0 = no returns)' },
|
|
388
|
+
return_condition: { type: 'string', description: 'Return conditions text (optional)' },
|
|
389
|
+
warranty_days: { type: 'number', description: 'Warranty days, default 0' },
|
|
373
390
|
// S2 库存预警
|
|
374
391
|
low_stock_threshold: {
|
|
375
392
|
type: 'number',
|
|
376
|
-
description: '
|
|
393
|
+
description: '[S2] Low-stock alert threshold (notify seller when ≤; 0 = disabled)',
|
|
377
394
|
},
|
|
378
395
|
auto_delist_on_zero: {
|
|
379
396
|
type: 'boolean',
|
|
380
|
-
description: '
|
|
397
|
+
description: '[S2] Auto-delist to warehouse when stock=0 (anti-oversell)',
|
|
381
398
|
},
|
|
382
399
|
// S3 跨境上架多语言
|
|
383
400
|
i18n_titles: {
|
|
384
401
|
type: 'object',
|
|
385
|
-
description: '
|
|
402
|
+
description: '[S3] Multilingual titles, keys = en/ja/ko/fr/de/es/pt/ru/ar, values ≤500 chars. zh uses title field. E.g. {"en":"Wireless Earbuds","ja":"ワイヤレスイヤホン"}',
|
|
386
403
|
},
|
|
387
404
|
i18n_descs: {
|
|
388
405
|
type: 'object',
|
|
389
|
-
description: '
|
|
406
|
+
description: '[S3] Multilingual descs, same structure as i18n_titles',
|
|
390
407
|
},
|
|
391
408
|
// S4 商品溯源(origin_claims)— 协议级可挑战
|
|
392
409
|
origin_claims: {
|
|
393
410
|
type: 'object',
|
|
394
|
-
description: '
|
|
411
|
+
description: '[S4] Product-origin claims (challengeable). E.g. {"made_in":"Kyoto JP","material":"100% cotton GOTS-cert","certs":[{"name":"GOTS","sha256":"<64-hex>"}]}. Total JSON ≤4KB; any cert sha256 must be 64-hex. Any buyer can challenge.',
|
|
395
412
|
},
|
|
396
413
|
},
|
|
397
414
|
required: ['api_key'],
|
|
@@ -399,49 +416,46 @@ Actions:
|
|
|
399
416
|
},
|
|
400
417
|
{
|
|
401
418
|
name: 'webaz_place_order',
|
|
402
|
-
|
|
419
|
+
// was ~1117 chars, now ~580 chars
|
|
420
|
+
description: `Buyer places order. Buyer api_key required. Funds auto-enter protocol escrow.
|
|
403
421
|
|
|
404
|
-
|
|
405
|
-
-
|
|
406
|
-
-
|
|
407
|
-
-
|
|
408
|
-
- delivery_deadline: T+336h (7d after pickup)
|
|
409
|
-
- confirm_deadline: T+408h (72h after delivery)
|
|
422
|
+
Order deadlines (absolute ISO timestamps in response):
|
|
423
|
+
- accept T+48h | ship T+120h (72h after accept)
|
|
424
|
+
- pickup T+168h (48h after ship) | delivery T+336h (7d after pickup)
|
|
425
|
+
- confirm T+408h (72h after delivery)
|
|
410
426
|
|
|
411
|
-
Missing any
|
|
427
|
+
Missing any → auto-judge fault against responsible party + compensation per protocol.
|
|
412
428
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
──
|
|
418
|
-
中文:买家下单 — 资金进托管。订单 6 个 deadline 都是绝对时间戳,每个相对前一步的允许时长:accept 24h→ship 72h→pickup 48h→deliver 7d→confirm 72h。任何一个超时由对应责任方违约。可选:跨境关税估算 / 匿名收件 / 慈善捐赠。`,
|
|
429
|
+
Options:
|
|
430
|
+
- **B1 cross-border tax**: server auto-estimates duty (seller's est_import_duty_pct × price)
|
|
431
|
+
- **B2 privacy**: \`anonymous_recipient=true\` → PR-XXXXX alias on shipping label
|
|
432
|
+
- **B5 donation**: \`donation_pct\` 0 / 0.5 / 1 / 2 / 5% → charity_fund`,
|
|
419
433
|
inputSchema: {
|
|
420
434
|
type: 'object',
|
|
421
435
|
properties: {
|
|
422
|
-
api_key: { type: 'string', description: '
|
|
423
|
-
product_id: { type: 'string', description: '
|
|
424
|
-
quantity: { type: 'number', description: '
|
|
425
|
-
shipping_address: { type: 'string', description: '
|
|
426
|
-
notes: { type: 'string', description: '
|
|
436
|
+
api_key: { type: 'string', description: "Buyer's api_key" },
|
|
437
|
+
product_id: { type: 'string', description: 'Product ID to buy (from webaz_search)' },
|
|
438
|
+
quantity: { type: 'number', description: 'Quantity, default 1' },
|
|
439
|
+
shipping_address: { type: 'string', description: 'Shipping address' },
|
|
440
|
+
notes: { type: 'string', description: 'Note to seller (optional)' },
|
|
427
441
|
session_token: {
|
|
428
442
|
type: 'string',
|
|
429
|
-
description: '
|
|
443
|
+
description: 'Price-lock session_token (recommended): from webaz_verify_price; guarantees order price = displayed price',
|
|
430
444
|
},
|
|
431
445
|
promoter_api_key: {
|
|
432
446
|
type: 'string',
|
|
433
|
-
description:
|
|
447
|
+
description: "Referrer api_key (optional). ⚠️ Only L1 recorded (direct referrer, 70% commission); L2/L3 can't be inferred via MCP, redirects per region rule (singapore-like high max_levels → charity chain_gap; global max_levels=1 → global_fund region cap). Full 7:2:1 three-tier chain requires buyer clicking ?ref= URL from webaz_share_link (creates product_share_attribution).",
|
|
434
448
|
},
|
|
435
449
|
// B2 隐私购物
|
|
436
450
|
anonymous_recipient: {
|
|
437
451
|
type: 'boolean',
|
|
438
|
-
description: '
|
|
452
|
+
description: '[B2] Anonymous recipient: system generates PR-XXXXX alias instead of real name (seller label shows alias + address only)',
|
|
439
453
|
},
|
|
440
454
|
// B5 公益捐赠(按订单总额百分比,定额选项防机器人滥用)
|
|
441
455
|
donation_pct: {
|
|
442
456
|
type: 'number',
|
|
443
457
|
enum: [0, 0.005, 0.01, 0.02, 0.05],
|
|
444
|
-
description: '
|
|
458
|
+
description: '[B5] Per-order donation pct (0 / 0.5 / 1 / 2 / 5). Computed separately + into charity_fund, posted on order complete.',
|
|
445
459
|
},
|
|
446
460
|
},
|
|
447
461
|
required: ['api_key', 'product_id', 'shipping_address'],
|
|
@@ -449,41 +463,28 @@ Missing any deadline auto-judges fault against the responsible party and trigger
|
|
|
449
463
|
},
|
|
450
464
|
{
|
|
451
465
|
name: 'webaz_update_order',
|
|
452
|
-
|
|
466
|
+
// was ~927 chars, now ~430 chars
|
|
467
|
+
description: `STATUS TRANSITIONS on an order — NOT for editing order content (price/qty/address immutable after creation). Each role can only perform their own actions.
|
|
453
468
|
|
|
454
|
-
|
|
469
|
+
- **Seller**: accept (24h after payment) | ship (needs tracking, within handling time)
|
|
470
|
+
- **Logistics**: pickup (48h after ship) | transit | deliver (needs proof description)
|
|
471
|
+
- **Buyer**: confirm (→ fund settlement) | dispute (needs reason; freezes funds → arbitration)
|
|
455
472
|
|
|
456
|
-
|
|
457
|
-
- accept: accept order (within 24h of payment)
|
|
458
|
-
- ship: confirm dispatch (needs tracking number, within promised handling time)
|
|
459
|
-
|
|
460
|
-
Logistics actions:
|
|
461
|
-
- pickup: confirm parcel pickup (within 48h of ship)
|
|
462
|
-
- transit: update to in-transit
|
|
463
|
-
- deliver: confirm delivery (needs delivery proof description)
|
|
464
|
-
|
|
465
|
-
Buyer actions:
|
|
466
|
-
- confirm: confirm receipt → triggers fund settlement
|
|
467
|
-
- dispute: raise dispute (needs reason; freezes funds pending arbitration)
|
|
468
|
-
|
|
469
|
-
If a deadline is missed, protocol auto-marks that party as in default.
|
|
470
|
-
|
|
471
|
-
──
|
|
472
|
-
中文:更新订单状态 — 角色专属 action(卖家 accept/ship · 物流 pickup/transit/deliver · 买家 confirm/dispute)。截止超时自动判违约。`,
|
|
473
|
+
Missing deadline → protocol auto-marks party in default.`,
|
|
473
474
|
inputSchema: {
|
|
474
475
|
type: 'object',
|
|
475
476
|
properties: {
|
|
476
|
-
api_key: { type: 'string', description: '
|
|
477
|
-
order_id: { type: 'string', description: '
|
|
477
|
+
api_key: { type: 'string', description: "Operator's api_key" },
|
|
478
|
+
order_id: { type: 'string', description: 'Order ID' },
|
|
478
479
|
action: {
|
|
479
480
|
type: 'string',
|
|
480
481
|
enum: ['accept', 'ship', 'pickup', 'transit', 'deliver', 'confirm', 'dispute'],
|
|
481
|
-
description: '
|
|
482
|
+
description: 'Action to execute',
|
|
482
483
|
},
|
|
483
|
-
notes: { type: 'string', description: '
|
|
484
|
+
notes: { type: 'string', description: 'Action note (e.g. tracking number, dispute reason)' },
|
|
484
485
|
evidence_description: {
|
|
485
486
|
type: 'string',
|
|
486
|
-
description: '
|
|
487
|
+
description: 'Evidence description (recommended for ship/pickup/deliver; required for dispute)',
|
|
487
488
|
},
|
|
488
489
|
},
|
|
489
490
|
required: ['api_key', 'order_id', 'action'],
|
|
@@ -491,43 +492,37 @@ If a deadline is missed, protocol auto-marks that party as in default.
|
|
|
491
492
|
},
|
|
492
493
|
{
|
|
493
494
|
name: 'webaz_get_status',
|
|
494
|
-
|
|
495
|
-
Requires api_key of
|
|
496
|
-
Returns: current status, status history (who did what when), next responsible actor, deadline.
|
|
497
|
-
|
|
498
|
-
──
|
|
499
|
-
中文:查订单状态 + 历史 + 当前责任方 + 截止时间。任一参与方可查。`,
|
|
495
|
+
// was ~286 chars, now ~200 chars
|
|
496
|
+
description: `Query order status + full history + current responsible party + deadline. Requires api_key of order participant (buyer/seller/logistics all OK). Returns: status / status_history (who did what when) / next_actor / deadline.`,
|
|
500
497
|
inputSchema: {
|
|
501
498
|
type: 'object',
|
|
502
499
|
properties: {
|
|
503
|
-
api_key: { type: 'string', description: '
|
|
504
|
-
order_id: { type: 'string', description: '
|
|
500
|
+
api_key: { type: 'string', description: "Querier's api_key" },
|
|
501
|
+
order_id: { type: 'string', description: 'Order ID' },
|
|
505
502
|
},
|
|
506
503
|
required: ['api_key', 'order_id'],
|
|
507
504
|
},
|
|
508
505
|
},
|
|
509
506
|
{
|
|
510
507
|
name: 'webaz_wallet',
|
|
511
|
-
|
|
508
|
+
// was ~788 chars, now ~440 chars
|
|
509
|
+
description: `Wallet **READ-ONLY** query (balance / earnings / deposit/withdrawal/income history).
|
|
512
510
|
|
|
513
|
-
⚠️ Iron-Rule
|
|
511
|
+
⚠️ **Iron-Rule**: actual withdrawals / deposits / whitelist mgmt need **PWA Web + Passkey + email OTP**. This tool CANNOT move money — only query. User asks "send/withdraw/deposit WAZ"? Do NOT promise via MCP — direct to PWA Web.
|
|
514
512
|
|
|
515
513
|
Actions:
|
|
516
|
-
- view
|
|
517
|
-
- deposits
|
|
518
|
-
- withdrawals
|
|
519
|
-
- income
|
|
520
|
-
|
|
521
|
-
──
|
|
522
|
-
中文:钱包查询(余额/收益/充提历史)。仅查询用,实际充提需 PWA Web + Passkey + 邮件 OTP,agent 不可绕过。`,
|
|
514
|
+
- view (default) — balance + staked + in-escrow + earnings + reputation tier
|
|
515
|
+
- deposits — last 10 on-chain (tx_hash / amount / block)
|
|
516
|
+
- withdrawals — last 10 (status / tx_hash)
|
|
517
|
+
- income — breakdown: referral L1/L2/L3 + binary PV matching + sales net`,
|
|
523
518
|
inputSchema: {
|
|
524
519
|
type: 'object',
|
|
525
520
|
properties: {
|
|
526
|
-
api_key: { type: 'string', description: '
|
|
521
|
+
api_key: { type: 'string', description: 'Your api_key' },
|
|
527
522
|
action: {
|
|
528
523
|
type: 'string',
|
|
529
524
|
enum: ['view', 'deposits', 'withdrawals', 'income'],
|
|
530
|
-
description: '
|
|
525
|
+
description: 'Action type (default: view)',
|
|
531
526
|
},
|
|
532
527
|
},
|
|
533
528
|
required: ['api_key'],
|
|
@@ -535,255 +530,185 @@ Actions:
|
|
|
535
530
|
},
|
|
536
531
|
{
|
|
537
532
|
name: 'webaz_notifications',
|
|
538
|
-
|
|
539
|
-
Agents should poll
|
|
540
|
-
Every status change (new order / ship / dispute / etc.) notifies relevant participants.
|
|
541
|
-
|
|
542
|
-
⚠️ Scope: 此工具只查 L2-6 system notifications。不含 / Does NOT include:
|
|
543
|
-
- chat unread(私信)→ 用 webaz_chat action=list
|
|
544
|
-
- announcements unread(管理员公告)→ 暂无 MCP 工具(PWA #me/announcements)
|
|
545
|
-
- feedback replies unread(用户反馈回复)→ 暂无 MCP 工具
|
|
546
|
-
PWA 顶部红点是 4 项合计;此工具仅返回第 1 项 → 数字可能 < PWA 显示。
|
|
547
|
-
PWA top badge aggregates all 4; this returns only 1 → may be < PWA shows.
|
|
533
|
+
// was ~608 chars, now ~330 chars
|
|
534
|
+
description: `Query user notifications (L2-6 system). Agents should poll periodically for pending order events (new order / ship / dispute → notifies relevant participants).
|
|
548
535
|
|
|
549
|
-
|
|
550
|
-
中文:查通知 — agent 定期调用检查待处理事件(新订单/发货/争议等会通知所有相关方)。`,
|
|
536
|
+
⚠️ **Scope**: only L2-6 system notifications. Does NOT include: chat unread (use webaz_chat list) | announcements | feedback replies. PWA top badge aggregates 4; this returns 1 → may be **<** PWA shows.`,
|
|
551
537
|
inputSchema: {
|
|
552
538
|
type: 'object',
|
|
553
539
|
properties: {
|
|
554
|
-
api_key: { type: 'string', description: '
|
|
555
|
-
unread: { type: 'boolean', description: '
|
|
556
|
-
mark_read: { type: 'boolean', description: '
|
|
540
|
+
api_key: { type: 'string', description: 'Your api_key' },
|
|
541
|
+
unread: { type: 'boolean', description: 'Return only unread (default false)' },
|
|
542
|
+
mark_read: { type: 'boolean', description: 'Auto-mark read after call (default false)' },
|
|
557
543
|
},
|
|
558
544
|
required: ['api_key'],
|
|
559
545
|
},
|
|
560
546
|
},
|
|
561
547
|
{
|
|
562
548
|
name: 'webaz_dispute',
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
⚠️ Different from webaz_claim_verify:
|
|
566
|
-
- webaz_dispute = order delivery problem (didn't arrive / wrong / damaged in transit / seller fraud) → central arbitrator + 120h ruling
|
|
567
|
-
- webaz_claim_verify = challenge a product CLAIM (brand / spec / ship time) → 3 crowd verifiers vote
|
|
568
|
-
Pick based on the actual problem: delivery/receiving = dispute; marketing-claim accuracy = claim_verify.
|
|
569
|
-
|
|
570
|
-
When buyer claims item-not-as-described / damaged / seller fraud, first raise dispute via webaz_update_order action=dispute,
|
|
571
|
-
then use this tool for follow-ups.
|
|
572
|
-
|
|
573
|
-
Protocol guarantees (no human intervention):
|
|
574
|
-
- Respondent has 48h to submit rebuttal evidence, else protocol auto-judges in initiator's favor
|
|
575
|
-
- Arbitrator has 120h to issue ruling, else protocol defaults to refund-buyer
|
|
576
|
-
- Once executed, ruling fund movement is instant and irreversible
|
|
549
|
+
// was ~2277 chars, now ~900 chars
|
|
550
|
+
description: `Manage ORDER-DELIVERY dispute lifecycle (L3, central arbitrator). For order delivery problems (not arrived / wrong / damaged / seller fraud). **NOT for challenging product marketing claims → use webaz_claim_verify.** Quick rule: did buyer receive item? Yes + item-itself issue → claim_verify. No / damaged-transit → dispute. Initial raise via webaz_update_order action=dispute, then this tool for follow-ups.
|
|
577
551
|
|
|
578
552
|
Actions:
|
|
579
|
-
- view
|
|
580
|
-
- list_open
|
|
581
|
-
- respond
|
|
582
|
-
- add_evidence
|
|
583
|
-
- arbitrate
|
|
553
|
+
- view dispute details (any participant)
|
|
554
|
+
- list_open pending disputes (arbitrators only)
|
|
555
|
+
- respond respondent rebuttal (before 48h deadline)
|
|
556
|
+
- add_evidence any participant supplements
|
|
557
|
+
- arbitrate ruling + fund disposition (assigned arbitrator only)
|
|
584
558
|
|
|
585
|
-
Ruling options (
|
|
586
|
-
- refund_buyer: full refund to buyer + partial stake forfeit from seller
|
|
587
|
-
- release_seller: release funds to seller (seller wins)
|
|
588
|
-
- partial_refund: partial refund (needs refund_amount); if third-party fault, set liable_party (user_id) → seller settled full, compensation deducted from liable party
|
|
589
|
-
- liability_split: distributed liability (Wave 3) — needs liability_parties: [{user_id, amount}] for proportional stake deductions
|
|
559
|
+
Ruling options: refund_buyer | release_seller | partial_refund (needs refund_amount; optional liable_party → 3rd-party fault, seller settled full + deducted from liable) | liability_split (needs liability_parties[]={user_id,amount}).
|
|
590
560
|
|
|
591
|
-
|
|
592
|
-
⚠️ Iron-Rule boundary (spec §4): arbitrate is a protocol iron-rule node requiring arbitrator to complete Passkey re-confirmation via PWA Web UI.
|
|
593
|
-
Direct agent calls return 412 HUMAN_PRESENCE_REQUIRED — DO NOT retry; instead, guide the user to the browser.
|
|
594
|
-
view / list_open / respond / add_evidence can be agent-proxied; only arbitrate needs human.
|
|
561
|
+
Protocol auto-judges (no human): respondent silent 48h → favor initiator; arbitrator silent 120h → refund_buyer. Executed rulings are instant + irreversible.
|
|
595
562
|
|
|
596
|
-
|
|
597
|
-
中文:管理争议(L3)。Actions: view / list_open / respond / add_evidence (agent 可代) · arbitrate (需 PWA + Passkey 人工)。被诉方 48h 反驳,仲裁员 120h 裁定,超时自动判。`,
|
|
563
|
+
⚠️ **Iron-Rule (spec §4)**: \`arbitrate\` needs PWA + Passkey real-human re-confirm. Direct agent call returns 412 HUMAN_PRESENCE_REQUIRED — **do NOT retry**, guide user to browser. view / list_open / respond / add_evidence are agent-proxyable.`,
|
|
598
564
|
inputSchema: {
|
|
599
565
|
type: 'object',
|
|
600
566
|
properties: {
|
|
601
|
-
api_key: { type: 'string', description: '
|
|
567
|
+
api_key: { type: 'string', description: "Operator's api_key" },
|
|
602
568
|
action: {
|
|
603
569
|
type: 'string',
|
|
604
570
|
enum: ['view', 'list_open', 'respond', 'add_evidence', 'arbitrate'],
|
|
605
|
-
description: '
|
|
571
|
+
description: 'Action to execute',
|
|
606
572
|
},
|
|
607
|
-
dispute_id: { type: 'string', description: '
|
|
608
|
-
order_id: { type: 'string', description: '
|
|
609
|
-
notes: { type: 'string', description: '
|
|
610
|
-
evidence_description: { type: 'string', description: '
|
|
573
|
+
dispute_id: { type: 'string', description: 'Dispute ID (required for respond/add_evidence/arbitrate; for view, dispute_id OR order_id)' },
|
|
574
|
+
order_id: { type: 'string', description: 'Order ID (alternative to dispute_id for view)' },
|
|
575
|
+
notes: { type: 'string', description: 'Response / rebuttal note (for respond)' },
|
|
576
|
+
evidence_description: { type: 'string', description: 'Evidence description (for respond/add_evidence)' },
|
|
611
577
|
ruling: {
|
|
612
578
|
type: 'string',
|
|
613
579
|
enum: ['refund_buyer', 'release_seller', 'partial_refund', 'liability_split'],
|
|
614
|
-
description: '
|
|
580
|
+
description: 'Ruling (required for arbitrate)',
|
|
615
581
|
},
|
|
616
|
-
refund_amount: { type: 'number', description: '
|
|
617
|
-
liable_party: { type: 'string', description: '
|
|
582
|
+
refund_amount: { type: 'number', description: 'Partial refund amount (only when ruling=partial_refund)' },
|
|
583
|
+
liable_party: { type: 'string', description: '3rd-party liable user_id (optional for partial_refund): refund deducted from this party, seller settled in full' },
|
|
618
584
|
liability_parties: {
|
|
619
585
|
type: 'array',
|
|
620
|
-
description: '
|
|
586
|
+
description: 'Liability allocation array (required for liability_split); each item { user_id, amount }',
|
|
621
587
|
items: {
|
|
622
588
|
type: 'object',
|
|
623
589
|
properties: {
|
|
624
|
-
user_id: { type: 'string', description: '
|
|
625
|
-
amount: { type: 'number', description: '
|
|
590
|
+
user_id: { type: 'string', description: 'Liable user_id' },
|
|
591
|
+
amount: { type: 'number', description: 'Amount this party owes (WAZ)' },
|
|
626
592
|
},
|
|
627
593
|
required: ['user_id', 'amount'],
|
|
628
594
|
},
|
|
629
595
|
},
|
|
630
|
-
ruling_reason: { type: 'string', description: '
|
|
596
|
+
ruling_reason: { type: 'string', description: 'Ruling reason (required for arbitrate; permanently recorded on-chain)' },
|
|
631
597
|
},
|
|
632
598
|
required: ['api_key', 'action'],
|
|
633
599
|
},
|
|
634
600
|
},
|
|
635
601
|
{
|
|
636
602
|
name: 'webaz_claim_verify',
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
⚠️ Different from webaz_dispute:
|
|
640
|
-
- webaz_claim_verify = challenge a CLAIM about the product itself ("seller said 24h ship but didn't" / "said brand new but used")
|
|
641
|
-
- webaz_dispute = order-delivery problem (didn't arrive / arrived broken / wrong item) → central arbitrator
|
|
642
|
-
If unsure: did the buyer GET the item? If yes + problem with item itself → claim_verify. If no/damaged in transit → dispute.
|
|
603
|
+
// was ~2917 chars, now ~1100 chars
|
|
604
|
+
description: `Crowd-sourced PRODUCT-CLAIM verification — challenge seller's marketing claims (brand / spec / ship time / authenticity). 3 eligible verifiers vote → consensus.
|
|
643
605
|
|
|
644
|
-
|
|
645
|
-
- Buyer: suspects a seller's product claim (e.g. "brand new sealed", "ships within 24h") → wants decentralized verification
|
|
646
|
-
- Seller: defends against an opened verification by submitting counter-evidence → extends task by 24h
|
|
647
|
-
- Verifier: browses open tasks, votes on eligible ones (pass/fail/no_fault/abstain), settles on 3rd vote
|
|
606
|
+
**vs webaz_dispute**: dispute = delivery problem (not arrived / damaged / wrong item, central arbitrator). claim_verify = item-itself / claim-accuracy ("said brand new but used", "said 24h ship but didn't"). Quick test: did buyer receive? Yes + item issue → claim_verify; No / transit damage → dispute.
|
|
648
607
|
|
|
649
608
|
Actions:
|
|
650
609
|
[Buyer]
|
|
651
|
-
- create
|
|
652
|
-
- view
|
|
653
|
-
- mine
|
|
654
|
-
|
|
610
|
+
- create open verification (locks 10 WAZ; order must be paid/delivered, NOT completed; settles on 3rd vote)
|
|
611
|
+
- view task details (visible to participants + voters + eligible verifiers)
|
|
612
|
+
- mine all my tasks (buyer/seller/verifier perspectives)
|
|
655
613
|
[Seller]
|
|
656
|
-
- submit_seller_evidence
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
-
|
|
660
|
-
- vote vote on a task (pass / fail / no_fault / abstain)
|
|
661
|
-
pass = seller's claim is true / product OK
|
|
662
|
-
fail = seller's claim is false / product mismatch
|
|
663
|
-
no_fault = neither party clearly at fault (dispute has merit but inconclusive)
|
|
664
|
-
abstain = "not my expertise, skipping" — not counted in 3-vote consensus, doesn't affect accuracy (V3 right-to-decline)
|
|
665
|
-
|
|
614
|
+
- submit_seller_evidence rebuttal → +24h extension
|
|
615
|
+
[Verifier]
|
|
616
|
+
- available list takeable tasks (eligibility: age≥60d / email verified / ≥20 completed orders / 0 arbitration losses / never suspended / wallet ≥200 WAZ / reputation ≥110)
|
|
617
|
+
- vote pass (claim true) | fail (claim false) | no_fault (inconclusive) | abstain (not my expertise — not counted, no accuracy impact)
|
|
666
618
|
[Become Verifier]
|
|
667
|
-
- eligibility
|
|
668
|
-
- verifier_status my quota / tier / stake
|
|
669
|
-
- apply apply to verifier whitelist (needs reputation + stake lock)
|
|
670
|
-
- withdraw_application withdraw application, refund stake
|
|
671
|
-
- appeal appeal a suspension (only when suspended)
|
|
672
|
-
|
|
673
|
-
─────────────────────
|
|
674
|
-
⚠️ Iron-Rule boundary (spec §4): vote is a protocol iron-rule node requiring verifier to complete Passkey re-confirmation via PWA Web UI.
|
|
675
|
-
Direct agent calls to vote return 412 HUMAN_PRESENCE_REQUIRED — DO NOT retry; instead, guide the user to the browser.
|
|
676
|
-
Other actions (create / view / mine / available / eligibility / apply / appeal etc.) can be agent-proxied; only vote needs human.
|
|
619
|
+
- eligibility / verifier_status / apply (needs stake) / withdraw_application / appeal (only when suspended)
|
|
677
620
|
|
|
678
|
-
|
|
679
|
-
中文:众包索赔验证 — 3 verifier 共识投票判定。买家创建、卖家反证、verifier 投票。仅 vote 需 PWA + Passkey 人工,其他 actions agent 可代。`,
|
|
621
|
+
⚠️ **Iron-Rule (spec §4)**: \`vote\` needs PWA + Passkey real-human re-confirm. Direct agent call returns 412 HUMAN_PRESENCE_REQUIRED — **do NOT retry**, guide user to browser. All other actions agent-proxyable.`,
|
|
680
622
|
inputSchema: {
|
|
681
623
|
type: 'object',
|
|
682
624
|
properties: {
|
|
683
|
-
api_key: { type: 'string', description: '
|
|
625
|
+
api_key: { type: 'string', description: 'Your api_key' },
|
|
684
626
|
action: {
|
|
685
627
|
type: 'string',
|
|
686
628
|
enum: ['create', 'view', 'mine', 'submit_seller_evidence', 'available', 'vote', 'eligibility', 'verifier_status', 'apply', 'withdraw_application', 'appeal'],
|
|
687
|
-
description: '
|
|
629
|
+
description: 'Action to execute',
|
|
688
630
|
},
|
|
689
631
|
// create
|
|
690
|
-
order_id: { type: 'string', description: '
|
|
632
|
+
order_id: { type: 'string', description: 'Order ID (required for create). Order status must be paid/delivered (cannot create on completed)' },
|
|
691
633
|
claim_target: {
|
|
692
634
|
type: 'string',
|
|
693
635
|
enum: ['price', 'commission', 'protection', 'return', 'warranty', 'handling', 'other'],
|
|
694
|
-
description: '
|
|
636
|
+
description: 'Claim target (required for create). 7 types: price / commission / protection / return / warranty / handling / other',
|
|
695
637
|
},
|
|
696
|
-
claim_text: { type: 'string', description: '
|
|
697
|
-
evidence_uri: { type: 'string', description: '
|
|
638
|
+
claim_text: { type: 'string', description: 'Claim text 6-500 chars (required for create). Locks 10 WAZ anti-spam (refunded if no fault)' },
|
|
639
|
+
evidence_uri: { type: 'string', description: 'Evidence URI (optional for create/vote/submit_seller_evidence; buyer/verifier/seller respective evidence)' },
|
|
698
640
|
// view / vote / submit_seller_evidence
|
|
699
|
-
task_id: { type: 'string', description: '
|
|
641
|
+
task_id: { type: 'string', description: 'Task ID (required for view/vote/submit_seller_evidence)' },
|
|
700
642
|
// vote
|
|
701
|
-
vote: { type: 'string', enum: ['pass', 'fail', 'no_fault', 'abstain'], description: 'vote
|
|
702
|
-
note: { type: 'string', description: '
|
|
643
|
+
vote: { type: 'string', enum: ['pass', 'fail', 'no_fault', 'abstain'], description: 'Required for vote; abstain = not my expertise (V3 right-to-decline)' },
|
|
644
|
+
note: { type: 'string', description: 'Vote note (optional for vote, ≤500 chars)' },
|
|
703
645
|
// appeal
|
|
704
|
-
reason: { type: 'string', description: '
|
|
646
|
+
reason: { type: 'string', description: 'Appeal reason (required for appeal, ≤500 chars)' },
|
|
705
647
|
},
|
|
706
648
|
required: ['api_key', 'action'],
|
|
707
649
|
},
|
|
708
650
|
},
|
|
709
651
|
{
|
|
710
652
|
name: 'webaz_skill',
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
USE THIS when:
|
|
714
|
-
- seller wants to install reusable selling behavior (auto-accept / catalog-sync / price-haggling / etc.), OR
|
|
715
|
-
- buyer agent wants to subscribe to seller's behaviour to enable priority discovery / auto-deal flows.
|
|
653
|
+
// was ~2251 chars, now ~920 chars
|
|
654
|
+
description: `L4-4 Skill marketplace — sellers publish reusable seller-side BEHAVIOUR configs; buyer Agents subscribe one-click.
|
|
716
655
|
|
|
717
|
-
NOT a product search
|
|
718
|
-
NOT a KNOWLEDGE-content marketplace — for buying/selling templates / prompts / guides / checklists use webaz_skill_market (totally separate system, independent revenue flow).
|
|
656
|
+
**NOT** a product search (use webaz_search). **NOT** a knowledge/content market (use webaz_skill_market — totally separate, independent revenue flow).
|
|
719
657
|
|
|
720
|
-
⚠️
|
|
658
|
+
⚠️ **Skill ≠ executable code distribution**. 5 typed kinds only, each accepts **structured config params** (numbers/enums/amounts). NO path for Agent to download/run arbitrary 3rd-party code. Subscribing = flag + data binding, NOT plugin install. Web2 "plugin marketplace" risk model does NOT apply.
|
|
721
659
|
|
|
722
|
-
|
|
723
|
-
buyer agents subscribe and auto-discover those sellers' products with priority; on sale, the Skill publisher earns referral commission.
|
|
660
|
+
Cold-start mechanism: Amazon/Shopify sellers integrate zero-cost; buyer agents auto-discover subscribed sellers with priority; publisher earns referral commission on sale.
|
|
724
661
|
|
|
725
|
-
Skill types (typed,
|
|
726
|
-
- catalog_sync
|
|
727
|
-
- auto_accept
|
|
728
|
-
- price_negotiation
|
|
729
|
-
- quality_guarantee
|
|
730
|
-
- instant_ship
|
|
662
|
+
Skill types (typed, not free-form):
|
|
663
|
+
- catalog_sync sync external store → subscribers see priority
|
|
664
|
+
- auto_accept auto-accept orders (config: min/max_amount, max_daily_orders)
|
|
665
|
+
- price_negotiation agent-side haggling (config: max_discount_pct, min_quantity)
|
|
666
|
+
- quality_guarantee extra stake compensation (config: guarantee_amount, coverage_days)
|
|
667
|
+
- instant_ship guarantee 24h dispatch (config: ship_within_hours)
|
|
731
668
|
|
|
732
|
-
Actions:
|
|
733
|
-
- list browse Skill marketplace (no auth)
|
|
734
|
-
- publish publish new Skill (sellers only)
|
|
735
|
-
- subscribe subscribe to a Skill (buyer perks)
|
|
736
|
-
- unsubscribe cancel subscription
|
|
737
|
-
- my_skills my published Skills (seller view)
|
|
738
|
-
- my_subs my subscribed Skills (buyer view)
|
|
739
|
-
|
|
740
|
-
──
|
|
741
|
-
中文:Skill 市场 — 卖家发布 agent 能力插件(catalog_sync / auto_accept / price_negotiation / quality_guarantee / instant_ship),买家 agent 订阅。Actions: list / publish / subscribe / unsubscribe / my_skills / my_subs。`,
|
|
669
|
+
Actions: list (no auth) | publish (seller) | subscribe / unsubscribe (buyer) | my_skills | my_subs.`,
|
|
742
670
|
inputSchema: {
|
|
743
671
|
type: 'object',
|
|
744
672
|
properties: {
|
|
745
|
-
api_key: { type: 'string', description: '
|
|
673
|
+
api_key: { type: 'string', description: 'Your api_key (omit for list)' },
|
|
746
674
|
action: {
|
|
747
675
|
type: 'string',
|
|
748
676
|
enum: ['list', 'publish', 'subscribe', 'unsubscribe', 'my_skills', 'my_subs'],
|
|
749
|
-
description: '
|
|
677
|
+
description: 'Action to execute',
|
|
750
678
|
},
|
|
751
679
|
// list 过滤参数
|
|
752
680
|
skill_type: {
|
|
753
681
|
type: 'string',
|
|
754
682
|
enum: ['catalog_sync', 'auto_accept', 'price_negotiation', 'quality_guarantee', 'instant_ship'],
|
|
755
|
-
description: '
|
|
683
|
+
description: 'Filter Skill type (optional for list)',
|
|
756
684
|
},
|
|
757
|
-
query: { type: 'string', description: '
|
|
685
|
+
query: { type: 'string', description: 'Keyword search (optional for list)' },
|
|
758
686
|
// publish 参数
|
|
759
|
-
name: { type: 'string', description: 'Skill
|
|
760
|
-
description: { type: 'string', description: 'Skill
|
|
761
|
-
category: { type: 'string', description: '
|
|
687
|
+
name: { type: 'string', description: 'Skill name (required for publish)' },
|
|
688
|
+
description: { type: 'string', description: 'Skill description (required for publish)' },
|
|
689
|
+
category: { type: 'string', description: 'Category (optional for publish)' },
|
|
762
690
|
config: {
|
|
763
691
|
type: 'object',
|
|
764
|
-
description: 'Skill
|
|
692
|
+
description: 'Skill config (optional for publish; e.g. auto_accept needs max_daily_orders)',
|
|
765
693
|
},
|
|
766
694
|
// subscribe 参数
|
|
767
|
-
skill_id: { type: 'string', description: 'Skill ID
|
|
695
|
+
skill_id: { type: 'string', description: 'Skill ID (required for subscribe/unsubscribe)' },
|
|
768
696
|
},
|
|
769
697
|
required: ['action'],
|
|
770
698
|
},
|
|
771
699
|
},
|
|
772
700
|
{
|
|
773
701
|
name: 'webaz_mykey',
|
|
774
|
-
|
|
702
|
+
// was ~909 chars, now ~480 chars
|
|
703
|
+
description: `Account RECOVERY check — confirm account existence by handle + 6-char permanent_code (from registration). Returns redacted api_key_hint only.
|
|
775
704
|
|
|
776
|
-
|
|
705
|
+
⚠️ **Iron-Rule**: full api_key disclosure requires **PWA + Passkey** verification — this MCP tool only returns hint + PWA URL, never full key.
|
|
777
706
|
|
|
778
|
-
|
|
707
|
+
USE THIS ONLY when user lost api_key + has handle + permanent_code. NOT for "show my api_key" (use the one you have). NOT for looking up others (use webaz_profile).
|
|
779
708
|
|
|
780
|
-
|
|
781
|
-
- found: boolean
|
|
782
|
-
- api_key_hint (e.g. "key_7d3d***faa7b") — confirms which account, never the full key
|
|
783
|
-
- full_api_key_recovery — instructions to use PWA for the real recovery
|
|
709
|
+
Rate-limited: 5/handle/hour; excessive → 1h lock.
|
|
784
710
|
|
|
785
|
-
|
|
786
|
-
中文:handle + permanent_code 双因素确认账户存在,仅返回 redact 过的 api_key_hint。完整 api_key 必须经 PWA + Passkey 二次验证(Iron-Rule)。同 handle 每小时最多 5 次。`,
|
|
711
|
+
Returns: found / api_key_hint (e.g. "key_7d3d***faa7b") / full_api_key_recovery URL.`,
|
|
787
712
|
inputSchema: {
|
|
788
713
|
type: 'object',
|
|
789
714
|
properties: {
|
|
@@ -795,44 +720,36 @@ Returns:
|
|
|
795
720
|
},
|
|
796
721
|
{
|
|
797
722
|
name: 'webaz_profile',
|
|
798
|
-
|
|
723
|
+
// was ~1076 chars, now ~570 chars
|
|
724
|
+
description: `View own profile / manage roles, AND view any user's public profile + content streams.
|
|
799
725
|
|
|
800
|
-
USE THIS
|
|
801
|
-
OR wants to see someone's listings / notes / activity stream. NOT for product keyword search — use webaz_search.
|
|
726
|
+
USE THIS for info about a SPECIFIC PERSON (by usr_xxx / permanent code / @handle / name), OR to see someone's listings / notes / activity stream. NOT for product keyword search — use webaz_search.
|
|
802
727
|
|
|
803
728
|
Self actions (need api_key):
|
|
804
|
-
- view
|
|
805
|
-
- add_role add a new role
|
|
806
|
-
- switch_role switch active role (one account can hold multiple roles)
|
|
729
|
+
- view (profile + wallet + api_key hint) | add_role | switch_role
|
|
807
730
|
|
|
808
731
|
Public-profile actions:
|
|
809
|
-
- view_user
|
|
810
|
-
- feed
|
|
811
|
-
secondhand | auctions | reviews | products | shares | reputation | pv | liked
|
|
812
|
-
(secondhand/auctions/reviews/products/shares/reputation are public;
|
|
813
|
-
pv needs api_key; liked is owner-only and needs your own api_key)
|
|
814
|
-
|
|
815
|
-
──
|
|
816
|
-
中文:看自己资料/管角色,也能看他人公开主页 + 内容流(二手/拍卖/测评/商品/笔记/信誉/PV/点赞)。Actions: view / add_role / switch_role / view_user / feed。`,
|
|
732
|
+
- view_user (user_id = usr_xxx / permanent_code / @handle; needs api_key)
|
|
733
|
+
- feed (user_id + feed): secondhand | auctions | reviews | products | shares | reputation (public) | pv (needs api_key) | liked (owner-only, needs your api_key)`,
|
|
817
734
|
inputSchema: {
|
|
818
735
|
type: 'object',
|
|
819
736
|
properties: {
|
|
820
|
-
api_key: { type: 'string', description: 'Your api_key
|
|
737
|
+
api_key: { type: 'string', description: 'Your api_key (required for view/add_role/switch_role/view_user; optional for public feed)' },
|
|
821
738
|
action: {
|
|
822
739
|
type: 'string',
|
|
823
740
|
enum: ['view', 'add_role', 'switch_role', 'view_user', 'feed'],
|
|
824
|
-
description: 'view/add_role/switch_role =
|
|
741
|
+
description: 'view/add_role/switch_role = self; view_user/feed = other user profile/feed',
|
|
825
742
|
},
|
|
826
743
|
role: {
|
|
827
744
|
type: 'string',
|
|
828
745
|
enum: ['buyer', 'seller', 'logistics', 'arbitrator'],
|
|
829
746
|
description: 'Role to add or switch to (required for add_role / switch_role)',
|
|
830
747
|
},
|
|
831
|
-
user_id: { type: 'string', description: '
|
|
748
|
+
user_id: { type: 'string', description: 'Target user: usr_xxx / permanent_code / @handle (required for view_user/feed)' },
|
|
832
749
|
feed: {
|
|
833
750
|
type: 'string',
|
|
834
751
|
enum: ['secondhand', 'auctions', 'reviews', 'products', 'shares', 'reputation', 'pv', 'liked'],
|
|
835
|
-
description: '
|
|
752
|
+
description: 'Feed type (required for feed)',
|
|
836
753
|
},
|
|
837
754
|
},
|
|
838
755
|
required: ['action'],
|
|
@@ -840,18 +757,14 @@ Public-profile actions:
|
|
|
840
757
|
},
|
|
841
758
|
{
|
|
842
759
|
name: 'webaz_revoke_key',
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
⚠️ STRONG RECOMMENDATION: use webaz_rotate_key instead unless you intentionally want zero replacement (e.g. fully decommissioning the agent / device). Rotate = atomic swap (no access gap). Revoke = death + you re-register from scratch.
|
|
760
|
+
// was ~778 chars, now ~430 chars
|
|
761
|
+
description: `Initiate api_key revocation (**NO REPLACEMENT** — old key dies, no new issued).
|
|
846
762
|
|
|
847
|
-
|
|
848
|
-
- You are PERMANENTLY decommissioning this agent / device, OR
|
|
849
|
-
- You want all access to die NOW with no fallback
|
|
763
|
+
⚠️ **Iron-Rule**: actual revocation needs **PWA + Passkey** confirm. MCP only registers intent + returns PWA URL.
|
|
850
764
|
|
|
851
|
-
|
|
765
|
+
⚠️ **STRONG REC**: use \`webaz_rotate_key\` instead unless you want zero replacement. Rotate = atomic swap (no access gap). Revoke = death + re-register.
|
|
852
766
|
|
|
853
|
-
|
|
854
|
-
中文:发起 api_key 吊销。Iron-Rule:真正吊销必须 PWA + Passkey 二次确认(agent 不能单方面执行不可逆操作)。MCP 仅登记意图,返回 PWA 确认 URL。`,
|
|
767
|
+
Use revoke when: PERMANENT decommission of agent/device, OR want access death NOW with no fallback. After PWA confirm: old key → 401 on all tools.`,
|
|
855
768
|
inputSchema: {
|
|
856
769
|
type: 'object',
|
|
857
770
|
properties: {
|
|
@@ -863,12 +776,10 @@ After PWA confirmation, the old api_key returns 401 on all tools.
|
|
|
863
776
|
},
|
|
864
777
|
{
|
|
865
778
|
name: 'webaz_rotate_key',
|
|
866
|
-
|
|
779
|
+
// was ~372 chars, now ~260 chars
|
|
780
|
+
description: `Initiate api_key rotation (invalidate old + issue new). ⚠️ **Iron-Rule**: needs **PWA + Passkey** confirm. After PWA: old → 401; new shown ONCE — store immediately.
|
|
867
781
|
|
|
868
|
-
Safer than webaz_revoke_key
|
|
869
|
-
|
|
870
|
-
──
|
|
871
|
-
中文:发起 api_key 轮换(旧 key 失效 + 新 key 同时签发)。比 revoke 安全,原子操作无访问中断。需 PWA + Passkey。`,
|
|
782
|
+
Safer than \`webaz_revoke_key\` — atomic swap, no access gap.`,
|
|
872
783
|
inputSchema: {
|
|
873
784
|
type: 'object',
|
|
874
785
|
properties: {
|
|
@@ -880,9 +791,11 @@ Safer than webaz_revoke_key because issuance is atomic with invalidation — no
|
|
|
880
791
|
},
|
|
881
792
|
{
|
|
882
793
|
name: 'webaz_referral',
|
|
883
|
-
description: `View your
|
|
794
|
+
description: `View your referral status: 3-tier commission (推土机) team + earnings + invite links + binary PV matching (原子能) tree + tier progress + L1 share permission gate + **rewards_status (RFC-002 §3.5 opt-in state + pending escrow)**.
|
|
795
|
+
|
|
796
|
+
⚠️ **Opt-in required (RFC-002)**: rewards default = off. \`rewards_status\` field returns 4-state {opted_in | never_activated | auto_downgraded | deactivated} + pending_escrow tally. Opted-out users still see attribution + tree, but commission held in escrow until activation via PWA #me.
|
|
884
797
|
|
|
885
|
-
⚠️
|
|
798
|
+
⚠️ **MLM disclosure**: structure may overlap with MLM legal definitions (see webaz_info.commission_model.compliance_notice). Agent acting for human user **MUST get explicit consent** before generating referral links / promoting. Do NOT auto-recruit.`,
|
|
886
799
|
inputSchema: {
|
|
887
800
|
type: 'object',
|
|
888
801
|
properties: {
|
|
@@ -893,9 +806,11 @@ Safer than webaz_revoke_key because issuance is atomic with invalidation — no
|
|
|
893
806
|
},
|
|
894
807
|
{
|
|
895
808
|
name: 'webaz_share_link',
|
|
896
|
-
description: `Generate
|
|
809
|
+
description: `Generate product share link with your referral attached. Open in any social platform (TikTok/WeChat/Telegram). Clicker registers/buys → counts toward your 3-tier commission (if verified buyer) + PV tree.
|
|
810
|
+
|
|
811
|
+
⚠️ **Opt-in required (RFC-002 §3.5)**: this is a valuation-layer action. Caller must have \`rewards_opted_in=1\` (builder-identity opt-in). Opted-out users get \`{error: 'rewards_opt_in_required', missing_requirements, next_steps}\` — direct user to PWA #me to apply.
|
|
897
812
|
|
|
898
|
-
⚠️
|
|
813
|
+
⚠️ **MLM disclosure**: builds referral chain (multi-tier commission + binary pairing). Agent acting for human user **MUST get explicit consent**. Do NOT auto-generate. See webaz_info.commission_model.compliance_notice.`,
|
|
899
814
|
inputSchema: {
|
|
900
815
|
type: 'object',
|
|
901
816
|
properties: {
|
|
@@ -912,17 +827,12 @@ Safer than webaz_revoke_key because issuance is atomic with invalidation — no
|
|
|
912
827
|
},
|
|
913
828
|
{
|
|
914
829
|
name: 'webaz_blocklist',
|
|
915
|
-
|
|
830
|
+
// was ~607 chars, now ~370 chars
|
|
831
|
+
description: `Manage blocklist of sellers/users. Blocked → auto-hidden from your search + can't follow them.
|
|
916
832
|
|
|
917
|
-
Scope (元规则 #5 不偏袒
|
|
918
|
-
- ✓ Hides blocked user's products from YOUR search results
|
|
919
|
-
- ✓ Prevents YOU from following them (webaz_follows respects this)
|
|
920
|
-
- ✗ Does NOT prevent placing orders on their products (商品发布即承诺销售 — public listing = sales commitment)
|
|
921
|
-
- ✗ Does NOT silence existing chat conversations (business context overrides)
|
|
922
|
-
- ✗ Does NOT prevent NEW chat starts on shared order/rfq context
|
|
923
|
-
- For active rejection: delist products, don't bid on RFQs, or cancel the order.
|
|
833
|
+
⚠️ **Scope** (元规则 #5 不偏袒): ✓ hides from YOUR search ✓ prevents follow. ✗ Does NOT prevent placing orders on their products (商品发布即承诺销售) ✗ Does NOT silence existing chat (business context wins) ✗ Does NOT prevent new chat on shared order/rfq context. For active rejection: delist / don't bid / cancel order.
|
|
924
834
|
|
|
925
|
-
|
|
835
|
+
Actions: list | block | unblock.`,
|
|
926
836
|
inputSchema: {
|
|
927
837
|
type: 'object',
|
|
928
838
|
properties: {
|
|
@@ -949,18 +859,12 @@ Returns the action result.`,
|
|
|
949
859
|
},
|
|
950
860
|
{
|
|
951
861
|
name: 'webaz_nearby',
|
|
952
|
-
|
|
862
|
+
// was ~831 chars, now ~430 chars
|
|
863
|
+
description: `Query anonymized nearby (~11km cell) purchase aggregation. **k-anonymity ≥3** privacy guard. Set/clear your coarse geo (0.1° precision, never exact GPS).
|
|
953
864
|
|
|
954
|
-
USE THIS
|
|
955
|
-
view, no specific keyword. NOT for "find product X" — use webaz_search. NOT for "items shippable
|
|
956
|
-
to my address" — use webaz_search ship_to filter.
|
|
865
|
+
USE THIS for "what's popular near me / 我附近 / 同城" — geo-aggregated, no keyword. NOT for "find product X" (use webaz_search). NOT for "shippable to me" (use webaz_search ship_to).
|
|
957
866
|
|
|
958
|
-
⚠️ MCP query
|
|
959
|
-
PWA #nearby 有【全网 / 同城 / 周边 / 14 公里】 4 档 fallback,无 location 也能看全网视图 —
|
|
960
|
-
这是设计性差异(MCP agent 应明示要 location,PWA UI 友好降级)。
|
|
961
|
-
⚠️ MCP query needs set_location first (else returns has_location: false).
|
|
962
|
-
PWA #nearby has 4-tier fallback (national/city/around/14km) showing global view without location —
|
|
963
|
-
by design (MCP demands location; PWA degrades gracefully).`,
|
|
867
|
+
⚠️ MCP \`query\` needs \`set_location\` first (else \`has_location: false\`). PWA #nearby has 4-tier fallback (national / city / around / 14km) — designed difference: MCP demands location, PWA degrades.`,
|
|
964
868
|
inputSchema: {
|
|
965
869
|
type: 'object',
|
|
966
870
|
properties: {
|
|
@@ -974,13 +878,10 @@ to my address" — use webaz_search ship_to filter.
|
|
|
974
878
|
},
|
|
975
879
|
{
|
|
976
880
|
name: 'webaz_default_address',
|
|
977
|
-
|
|
881
|
+
// was ~370 chars, now ~230 chars
|
|
882
|
+
description: `Read or set default shipping address. Used by webaz_search unshippable filter + fallback for webaz_rfq/place_order if omitted.
|
|
978
883
|
|
|
979
|
-
⚠️ set
|
|
980
|
-
不接受 structured 字段(recipient/line1/city/country/phone 等)— 跟传统电商地址 API 不同,agent 必须自己拼接。
|
|
981
|
-
|
|
982
|
-
──
|
|
983
|
-
中文:读取/设置默认收货地址。set 需要 text 必填 + region 可选;不收 structured 字段。`,
|
|
884
|
+
⚠️ \`set\` accepts only 2 fields: \`text\` (free-text address, ≤200 chars, required) + \`region\` (optional, for unshippable filter, ≤40 chars). NO structured fields (no recipient/line1/city/country/phone) — agent must concat itself.`,
|
|
984
885
|
inputSchema: {
|
|
985
886
|
type: 'object',
|
|
986
887
|
properties: {
|
|
@@ -994,16 +895,14 @@ to my address" — use webaz_search ship_to filter.
|
|
|
994
895
|
},
|
|
995
896
|
{
|
|
996
897
|
name: 'webaz_shareables',
|
|
997
|
-
|
|
898
|
+
// was ~843 chars, now ~480 chars
|
|
899
|
+
description: `Bind your **EXISTING external content** (YouTube / TikTok / 小红书 / B站 / IG / Twitter) to a WebAZ product/anchor — turns your content into referral-earning channel. WebAZ indexes only URL, never content bytes.
|
|
998
900
|
|
|
999
|
-
USE THIS when:
|
|
1000
|
-
- creator/user wants to "anchor" their existing review/unboxing/recommendation video/post to a WebAZ product (or anchor) so future buyers clicking that content → registration / purchase counts toward THEIR referral commission, OR
|
|
1001
|
-
- agent wants to look up "what external content is associated with this product / this anchor"
|
|
901
|
+
USE THIS when: creator anchors existing review/unboxing post → future buyers click → counts toward THEIR referral commission. OR agent looks up "what external content for this product/anchor".
|
|
1002
902
|
|
|
1003
|
-
|
|
903
|
+
⚠️ Different from \`webaz_share_link\` (generates NEW short link) — shareables register EXISTING content as discovery surface.
|
|
1004
904
|
|
|
1005
|
-
|
|
1006
|
-
中文:把你在 YouTube/TikTok/小红书/B站/IG/Twitter 已发的内容(测评/开箱/推荐)锚定到 WebAZ 商品 —— 让你的外部内容变成赚 referral 佣金的入口。WebAZ 只锚 URL,不取内容。区别于 webaz_share_link(那个是生成新短链)。`,
|
|
905
|
+
Actions: list_mine | add (external_url + product/anchor) | delete | by_product | by_anchor.`,
|
|
1007
906
|
inputSchema: {
|
|
1008
907
|
type: 'object',
|
|
1009
908
|
properties: {
|
|
@@ -1022,76 +921,63 @@ Differs from webaz_share_link (which generates a NEW short link for sharing) —
|
|
|
1022
921
|
// ── P3 RFQ / bid / chat / auto_bid(MCP 通过 HTTP 调 PWA,复用所有校验+状态机)────
|
|
1023
922
|
{
|
|
1024
923
|
name: 'webaz_rfq',
|
|
1025
|
-
|
|
924
|
+
// was ~1822 chars, now ~880 chars
|
|
925
|
+
description: `RFQ (Request-for-Quotation) — buyer posts demand, sellers bid within time window.
|
|
1026
926
|
|
|
1027
|
-
USE THIS when buyer wants
|
|
1028
|
-
webaz_search returned no good match, OR the buyer wants competing quotes (bulk / custom / unusual
|
|
1029
|
-
spec / time-sensitive). NOT a search tool. For browsing existing listings use webaz_search.
|
|
927
|
+
USE THIS when buyer POSTS a need (no good search match / bulk / custom / time-sensitive / wants competing quotes). NOT a search tool — for browsing use webaz_search. For AUCTION (English forward on a listed item) use webaz_auction.
|
|
1030
928
|
|
|
1031
929
|
Actions:
|
|
1032
|
-
- create (buyer)
|
|
1033
|
-
- mine (buyer)
|
|
1034
|
-
- browse (seller)
|
|
1035
|
-
- detail
|
|
1036
|
-
- award (buyer)
|
|
1037
|
-
- cancel (buyer)
|
|
930
|
+
- create (buyer) publish RFQ (title/qty/max_price/category/urgency/award_mode)
|
|
931
|
+
- mine (buyer) my RFQ list
|
|
932
|
+
- browse (seller) board view (filter by region/category/urgency/unbidded)
|
|
933
|
+
- detail full detail (buyer sees all bids; seller sees only own)
|
|
934
|
+
- award (buyer) pick winner (bid_id for manual; omit = auto-lowest)
|
|
935
|
+
- cancel (buyer) only pre-award; 30% deposit forfeit to charity_fund
|
|
1038
936
|
|
|
1039
937
|
Economics:
|
|
1040
|
-
- Buyer deposit = clamp(0.1, 1) of
|
|
1041
|
-
-
|
|
1042
|
-
-
|
|
1043
|
-
-
|
|
1044
|
-
- Award winner → standard order lifecycle, BUT with snapshot_commission_rate = 0 (RFQ orders 0% commission — direct deal between buyer/seller, no promoter chain to compensate). Seller gets price minus protocol_fee (2%) and fund_base (1%); no L1/L2/L3 dilution.
|
|
1045
|
-
- Seller bid stake (4.5+ WAZ) becomes bid_stake_held on the order; released to seller balance on successful complete; 50/50 split to buyer+sys_protocol on fault_seller (settleFault).
|
|
1046
|
-
- Window defaults: now=15min / today=60min / flex=1440min(24h)
|
|
1047
|
-
|
|
1048
|
-
Shipping address: if omitted, falls back to webaz_default_address (set via that tool first).
|
|
938
|
+
- Buyer deposit = clamp(0.1, 1) of max_price × qty × 1% (anti-spam). No-max-price = 0.1 WAZ flat.
|
|
939
|
+
- Seller bid stake = max(0.5, price × qty × 5%). Becomes bid_stake_held on award; released on complete; 50/50 split (buyer + sys_protocol) on fault_seller.
|
|
940
|
+
- Award → standard order lifecycle BUT **snapshot_commission_rate = 0** (RFQ 0% commission, no L1/L2/L3 promoter dilution); seller gets price − protocol_fee 2% − fund_base 1%.
|
|
941
|
+
- Window defaults: now=15min / today=60min / flex=24h.
|
|
1049
942
|
|
|
1050
|
-
|
|
1051
|
-
中文:求购单 RFQ。买家押金 1%(封顶 1 WAZ,仅防 spam);卖家 bid stake 5%(最少 0.5 WAZ);撤单扣 30% 入慈善池。`,
|
|
943
|
+
Shipping address falls back to webaz_default_address if omitted.`,
|
|
1052
944
|
inputSchema: {
|
|
1053
945
|
type: 'object',
|
|
1054
946
|
properties: {
|
|
1055
|
-
api_key: { type: 'string', description: '
|
|
947
|
+
api_key: { type: 'string', description: 'Your api_key' },
|
|
1056
948
|
action: { type: 'string', enum: ['create', 'mine', 'browse', 'detail', 'award', 'cancel'] },
|
|
1057
949
|
// create
|
|
1058
950
|
title: { type: 'string' },
|
|
1059
951
|
qty: { type: 'number' },
|
|
1060
|
-
max_price: { type: 'number', description: 'WAZ
|
|
952
|
+
max_price: { type: 'number', description: 'Max budget in WAZ (optional; if omitted, buyer deposit = 1 WAZ)' },
|
|
1061
953
|
category: { type: 'string', enum: ['standard', 'general', 'highvalue', 'restricted'] },
|
|
1062
954
|
urgency: { type: 'string', enum: ['now', 'today', 'flex'] },
|
|
1063
955
|
award_mode: { type: 'string', enum: ['manual', 'first_match', 'time_window'] },
|
|
1064
956
|
award_window_min: { type: 'number' },
|
|
1065
957
|
notes: { type: 'string' },
|
|
1066
|
-
shipping_address: { type: 'string', description: '
|
|
958
|
+
shipping_address: { type: 'string', description: 'Optional; falls back to buyer default address' },
|
|
1067
959
|
// browse filters
|
|
1068
960
|
region: { type: 'string' },
|
|
1069
961
|
unbidded: { type: 'boolean' },
|
|
1070
962
|
// detail/award/cancel
|
|
1071
963
|
rfq_id: { type: 'string' },
|
|
1072
|
-
bid_id: { type: 'string', description: 'award
|
|
964
|
+
bid_id: { type: 'string', description: 'Optional for award — if omitted, auto-pick current lowest bid' },
|
|
1073
965
|
},
|
|
1074
966
|
required: ['api_key', 'action'],
|
|
1075
967
|
},
|
|
1076
968
|
},
|
|
1077
969
|
{
|
|
1078
970
|
name: 'webaz_bid',
|
|
971
|
+
// was ~733 chars, now ~400 chars
|
|
1079
972
|
description: `Bid on RFQs (seller-side, Request-for-Quotation).
|
|
1080
973
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
Actions:
|
|
1084
|
-
- submit: new bid; needs rfq_id + price + qty_offered + fulfillment_type; optional eta_hours/note
|
|
1085
|
-
- patch: edit price/ETA/fulfillment/note (only active; stake delta auto-settled)
|
|
1086
|
-
- cancel: withdraw (only active; deposit released immediately)
|
|
1087
|
-
- list_mine: full bid history
|
|
974
|
+
⚠️ **ONLY for RFQ bidding** (buyer posted demand via webaz_rfq). For AUCTION (English forward on listed item) use \`webaz_auction action=bid\` — separate systems with different economics (RFQ = bid stake; auction = min_increment + sniper extension).
|
|
1088
975
|
|
|
1089
|
-
|
|
1090
|
-
中文:对 RFQ 报价(卖家)。Actions: submit / patch / cancel / list_mine。改价时 stake 自动结算差额。`,
|
|
976
|
+
Actions: submit (rfq_id + price + qty_offered + fulfillment_type; optional eta/note) | patch (active only, stake delta auto-settled) | cancel (active only, deposit released immediately) | list_mine.`,
|
|
1091
977
|
inputSchema: {
|
|
1092
978
|
type: 'object',
|
|
1093
979
|
properties: {
|
|
1094
|
-
api_key: { type: 'string', description: '
|
|
980
|
+
api_key: { type: 'string', description: 'Seller api_key' },
|
|
1095
981
|
action: { type: 'string', enum: ['submit', 'patch', 'cancel', 'list_mine'] },
|
|
1096
982
|
rfq_id: { type: 'string' },
|
|
1097
983
|
bid_id: { type: 'string' },
|
|
@@ -1100,42 +986,25 @@ Actions:
|
|
|
1100
986
|
eta_hours: { type: 'number' },
|
|
1101
987
|
fulfillment_type: { type: 'string', enum: ['instant_pickup', 'same_day', 'next_day', 'standard'] },
|
|
1102
988
|
note: { type: 'string' },
|
|
1103
|
-
offer_id: { type: 'string', description: '
|
|
989
|
+
offer_id: { type: 'string', description: 'Optional; reference existing offer' },
|
|
1104
990
|
},
|
|
1105
991
|
required: ['api_key', 'action'],
|
|
1106
992
|
},
|
|
1107
993
|
},
|
|
1108
994
|
{
|
|
1109
995
|
name: 'webaz_chat',
|
|
1110
|
-
|
|
996
|
+
// was ~1963 chars, now ~860 chars
|
|
997
|
+
description: `Relay buyer↔seller (or RFQ partner) MESSAGES — **context-bound DM**, NO open DM. Only \`order\` / \`rfq\` / \`listing_qa\` contexts.
|
|
1111
998
|
|
|
1112
|
-
USE THIS
|
|
1113
|
-
Actions:
|
|
1114
|
-
- start: open conversation — needs kind + context_id (for rfq, also recipient_id)
|
|
1115
|
-
- list: my conversation list
|
|
1116
|
-
- read: read messages (last 50; flag_reasons is array)
|
|
1117
|
-
- send: send message (anti-scam regex; matches get flagged=true but still delivered; flag_reasons is array)
|
|
1118
|
-
- mark_read: mark as read
|
|
1119
|
-
- block: block this specific conversation (sets conv.status=blocked; ≠ webaz_blocklist which hides from search)
|
|
999
|
+
USE THIS for trade communication ("ask seller about return", "tell buyer about delay", "answer listing Q&A"). NOT general LLM chat — every message attaches to context. User chatting with agent? Don't call this.
|
|
1120
1000
|
|
|
1121
|
-
|
|
1122
|
-
phone_cn (CN mobile 11-digit), wechat (微信/vx/wechat/weixin), alipay (支付宝/alipay),
|
|
1123
|
-
qq (qq:digits), bank_card (16-19 consecutive digits), telegram (@handle/t.me/telegram),
|
|
1124
|
-
external_url (any http(s) URL except localhost/webaz.app/webaz.io).
|
|
1001
|
+
Actions: start (kind + context_id; rfq needs recipient_id) | list | read (last 50, flag_reasons array) | send (anti-scam regex; matches flagged=true but still delivered) | mark_read | block (this conv only; ≠ webaz_blocklist which hides from search).
|
|
1125
1002
|
|
|
1126
|
-
|
|
1127
|
-
- Short-term: 60 messages / minute / user
|
|
1128
|
-
- AGENT_DAILY_CAP (reset at UTC midnight): new=30, trusted=100, quality=300, legend=1000
|
|
1129
|
-
(returns 429 + error_code=AGENT_DAILY_CAP + cap + used + level fields)
|
|
1130
|
-
3 overruns/day → auto agent warning strike.
|
|
1003
|
+
⚠️ **Anti-scam regex** (in flag_reasons[]): phone_cn (11-digit) / wechat (微信/vx/wechat) / alipay / qq / bank_card (16-19 digits) / telegram (@/t.me) / external_url (non-webaz HTTPS).
|
|
1131
1004
|
|
|
1132
|
-
|
|
1133
|
-
silences the specific conv. Existing conversations are NOT auto-silenced by webaz_blocklist
|
|
1134
|
-
(business context overrides — block prevents future ad-hoc contact but keeps active deal channels open).
|
|
1005
|
+
Rate limits: 60/min/user short-term + AGENT_DAILY_CAP (UTC reset): new=30 / trusted=100 / quality=300 / legend=1000 (over → 429 + error_code=AGENT_DAILY_CAP). 3 overruns/day → auto warning strike.
|
|
1135
1006
|
|
|
1136
|
-
|
|
1137
|
-
中文:上下文私聊 — 仅 order/rfq/listing_qa 三种场景可发起,无自由 DM。Actions: start / list / read / send / mark_read / block。
|
|
1138
|
-
反诈 regex 7 类 + 60/min rate limit。blocklist 不影响已建立 conversation(商业上下文优先)。`,
|
|
1007
|
+
webaz_blocklist hides from search but does NOT auto-silence existing convs (business context wins) — use this tool's \`block\` for per-conv silence.`,
|
|
1139
1008
|
inputSchema: {
|
|
1140
1009
|
type: 'object',
|
|
1141
1010
|
properties: {
|
|
@@ -1145,60 +1014,45 @@ silences the specific conv. Existing conversations are NOT auto-silenced by weba
|
|
|
1145
1014
|
context_id: { type: 'string' },
|
|
1146
1015
|
recipient_id: { type: 'string' },
|
|
1147
1016
|
conversation_id: { type: 'string' },
|
|
1148
|
-
body: { type: 'string', description: 'send action
|
|
1017
|
+
body: { type: 'string', description: 'Message body for send action (≤2000 chars)' },
|
|
1149
1018
|
},
|
|
1150
1019
|
required: ['api_key', 'action'],
|
|
1151
1020
|
},
|
|
1152
1021
|
},
|
|
1153
1022
|
{
|
|
1154
1023
|
name: 'webaz_price_history',
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
- windows: { d30, d90, lifetime } each {sales, volume, avg, median, p25, p75}
|
|
1158
|
-
- price_buckets: distribution array [{price, count, qty, pct}]
|
|
1159
|
-
- daily_avg: 30-day daily avg price trend [{date, sales, avg}]
|
|
1160
|
-
- category_avg_30d: same-category 30-day average
|
|
1161
|
-
- anomaly_flags: ('current_below_70pct_median' / 'far_below_category_avg' / 'far_above_category_avg')
|
|
1162
|
-
Returns insufficient_data:true when data sparse.
|
|
1024
|
+
// was ~571 chars, now ~350 chars
|
|
1025
|
+
description: `Product historical sale price + volume — helps agents avoid bottom-price dumping bait.
|
|
1163
1026
|
|
|
1164
|
-
|
|
1165
|
-
中文:商品历史成交价 + 量分布 — 防底价倾销。返回多时窗统计 + 价位分布 + 同类均价 + 异常预警。`,
|
|
1027
|
+
Returns: windows {d30, d90, lifetime} each {sales, volume, avg, median, p25, p75} | price_buckets [{price, count, qty, pct}] | daily_avg (30-day trend) | category_avg_30d | anomaly_flags (current_below_70pct_median / far_below_category_avg / far_above_category_avg). \`insufficient_data: true\` if sparse.`,
|
|
1166
1028
|
inputSchema: {
|
|
1167
1029
|
type: 'object',
|
|
1168
1030
|
properties: {
|
|
1169
|
-
product_id: { type: 'string', description: '
|
|
1031
|
+
product_id: { type: 'string', description: 'Product ID' },
|
|
1170
1032
|
},
|
|
1171
1033
|
required: ['product_id'],
|
|
1172
1034
|
},
|
|
1173
1035
|
},
|
|
1174
1036
|
{
|
|
1175
1037
|
name: 'webaz_charity',
|
|
1176
|
-
|
|
1038
|
+
// was ~1856 chars, now ~850 chars
|
|
1039
|
+
description: `Charity wish pool + repayment + community fund — double-anonymous + dual-signed anchoring + isolated prestige.
|
|
1177
1040
|
|
|
1178
|
-
USE THIS
|
|
1179
|
-
- user wants to publish a "wish" (need help with money/service) for community fulfillment, OR
|
|
1180
|
-
- user wants to claim/fulfill someone else's wish, OR
|
|
1181
|
-
- user wants to donate to / browse the community charity fund (separate from per-order donation).
|
|
1041
|
+
USE THIS for: publishing wish (need help) | claiming/fulfilling others' wishes | donating to / browsing community fund.
|
|
1182
1042
|
|
|
1183
|
-
NOT for per-order charity donation — that's
|
|
1184
|
-
Actions:
|
|
1185
|
-
- list: browse public wishes (filter by category/target_kind; anonymous accessible)
|
|
1186
|
-
- detail: single wish details (commit_hash + fulfillment + repayments)
|
|
1187
|
-
- create: (auth) publish a wish
|
|
1188
|
-
- claim: (auth) fulfiller claims (1:1 exclusive; 30-day self-claim lock; auto-release if no proof in 48h)
|
|
1189
|
-
- proof: (auth) submit completion evidence
|
|
1190
|
-
- confirm: (auth) wisher confirms → fulfiller +10 prestige
|
|
1191
|
-
- disclose: (auth) apply for public disclosure (both parties must agree)
|
|
1192
|
-
- cancel: (auth) wisher cancels (only open wishes)
|
|
1193
|
-
- me: (auth) my charity profile (prestige breakdown + pending repayment queue)
|
|
1194
|
-
- stories / leaderboard: public
|
|
1195
|
-
- repay: (auth) wisher initiates repayment (≥ 0.1 WAZ; auto-accepted if no response in 7d)
|
|
1196
|
-
- repay_respond:(auth) fulfiller responds (accept | decline_to_fund) — decline → funds go to community fund, wisher +8 / fulfiller +2 grace
|
|
1197
|
-
- donate: (auth) donate to community fund (≥ 0.1 WAZ; daily 50 WAZ matched 1:1 → donation_honor)
|
|
1198
|
-
- fund: fund balance + ledger + philanthropist leaderboard (public)
|
|
1043
|
+
**NOT** for per-order charity donation — that's webaz_place_order's \`donation_pct\` (0.5/1/2/5% to charity_fund at order time). This tool is the **standalone wish-fulfillment economy**.
|
|
1199
1044
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1045
|
+
Actions (15):
|
|
1046
|
+
- list / detail / stories / leaderboard / fund — public
|
|
1047
|
+
- create (auth) publish wish
|
|
1048
|
+
- claim (auth) 1:1 exclusive, 30-day self-claim lock, auto-release if no proof 48h
|
|
1049
|
+
- proof / confirm (auth) complete + wisher confirm → fulfiller +10 prestige
|
|
1050
|
+
- disclose (auth) both-agree public disclosure
|
|
1051
|
+
- cancel (auth) only open wishes
|
|
1052
|
+
- me (auth) prestige breakdown + pending repayment queue
|
|
1053
|
+
- repay (auth) ≥0.1 WAZ; auto-accept if no response 7d
|
|
1054
|
+
- repay_respond (auth) accept | decline_to_fund (decline → fund, wisher +8 / fulfiller +2 grace)
|
|
1055
|
+
- donate (auth) ≥0.1 WAZ; daily 50 WAZ matched 1:1 → donation_honor`,
|
|
1202
1056
|
inputSchema: {
|
|
1203
1057
|
type: 'object',
|
|
1204
1058
|
properties: {
|
|
@@ -1210,14 +1064,14 @@ Actions:
|
|
|
1210
1064
|
choice: { type: 'string', enum: ['accept', 'decline_to_fund'] },
|
|
1211
1065
|
category: { type: 'string', enum: ['medical', 'education', 'daily', 'elderly', 'disaster', 'tech', 'other'] },
|
|
1212
1066
|
target_kind: { type: 'string', enum: ['item', 'service', 'cash'] },
|
|
1213
|
-
target_waz: { type: 'number', description: 'cash
|
|
1214
|
-
escrow_self: { type: 'number', description: '1
|
|
1067
|
+
target_waz: { type: 'number', description: 'Required for cash mode, ≤500' },
|
|
1068
|
+
escrow_self: { type: 'number', description: '1=self-escrow lock full amount; 0=pure coordination' },
|
|
1215
1069
|
title: { type: 'string' }, content: { type: 'string' },
|
|
1216
|
-
window_hours: { type: 'number', description: '24-720
|
|
1070
|
+
window_hours: { type: 'number', description: '24-720 hours' },
|
|
1217
1071
|
allow_public: { type: 'number' },
|
|
1218
1072
|
proof_hash: { type: 'string', description: 'sha256 hex of proof_text' },
|
|
1219
1073
|
proof_note: { type: 'string' },
|
|
1220
|
-
amount: { type: 'number', description: 'repay / donate
|
|
1074
|
+
amount: { type: 'number', description: 'repay / donate amount in WAZ' },
|
|
1221
1075
|
note: { type: 'string' },
|
|
1222
1076
|
limit: { type: 'number' },
|
|
1223
1077
|
},
|
|
@@ -1226,20 +1080,15 @@ Actions:
|
|
|
1226
1080
|
},
|
|
1227
1081
|
{
|
|
1228
1082
|
name: 'webaz_p2p_product',
|
|
1083
|
+
// was ~880 chars, now ~480 chars
|
|
1229
1084
|
description: `P2P native store — product detail lives on seller's node; WebAZ only anchors hash + key fields.
|
|
1230
|
-
Actions:
|
|
1231
|
-
- create (seller): publish anchor — needs title/price/stock + content_hash (sha256) + content_signature (HMAC-SHA256(api_key, hash|signed_at))
|
|
1232
|
-
- list: browse public P2P products (incl. hash + peer_endpoint)
|
|
1233
|
-
- detail: single product (incl. hash + endpoint; agent should self-fetch peer_endpoint and verify sha256)
|
|
1234
|
-
- patch (seller): edit (price/stock/title direct; detail JSON change → must re-sign hash + signature)
|
|
1235
1085
|
|
|
1236
|
-
|
|
1086
|
+
Actions: create (seller, needs title/price/stock + content_hash sha256 + content_signature HMAC-SHA256(api_key, hash|signed_at)) | list | detail | patch (price/stock/title direct; detail JSON change → must re-sign).
|
|
1087
|
+
|
|
1088
|
+
⚠️ **Agent verification flow** (must implement):
|
|
1237
1089
|
1. GET peer_endpoint/<product_id> → raw JSON
|
|
1238
1090
|
2. canonicalize (sort keys, drop nulls) → JSON.stringify
|
|
1239
|
-
3. sha256(canonical) === product.content_hash ? accept : reject trade
|
|
1240
|
-
|
|
1241
|
-
──
|
|
1242
|
-
中文:P2P 原生商店 — 商品详情存卖家节点,WebAZ 只锚定 hash + 关键字段。Actions: create / list / detail / patch。Agent 须自行 GET peer_endpoint 校验 sha256。`,
|
|
1091
|
+
3. sha256(canonical) === product.content_hash ? accept : **reject trade**`,
|
|
1243
1092
|
inputSchema: {
|
|
1244
1093
|
type: 'object',
|
|
1245
1094
|
properties: {
|
|
@@ -1259,14 +1108,12 @@ Verification flow (agent implements):
|
|
|
1259
1108
|
},
|
|
1260
1109
|
{
|
|
1261
1110
|
name: 'webaz_like',
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
- status
|
|
1266
|
-
Threshold: must have ≥1 completed order (anti-Sybil). One vote per person, can't like own.
|
|
1111
|
+
// was ~369 chars, now ~230 chars
|
|
1112
|
+
description: `Like a shareable to boost product ranking.
|
|
1113
|
+
|
|
1114
|
+
Actions: toggle (same endpoint; 2nd call auto-unlikes) | status (my like status + total).
|
|
1267
1115
|
|
|
1268
|
-
|
|
1269
|
-
中文:对 shareable 点赞 — 提升商品 ranking。Actions: toggle / status。门槛:≥1 完成订单,不能给自己点。`,
|
|
1116
|
+
⚠️ **Anti-Sybil**: must have ≥1 completed order. One vote per person, can't like own.`,
|
|
1270
1117
|
inputSchema: {
|
|
1271
1118
|
type: 'object',
|
|
1272
1119
|
properties: {
|
|
@@ -1279,49 +1126,43 @@ Threshold: must have ≥1 completed order (anti-Sybil). One vote per person, can
|
|
|
1279
1126
|
},
|
|
1280
1127
|
{
|
|
1281
1128
|
name: 'webaz_leaderboard',
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
- products trending products (rank_score = sales×0.5 + referrals×2.0 + likes×1.0)
|
|
1285
|
-
- value_products value-certified (💎 cheapest 20% per category · daily batch)
|
|
1286
|
-
- creators creator board (by total likes received)
|
|
1287
|
-
- sellers seller board (by rating × log(reviews+1); GMV hidden)
|
|
1288
|
-
- buyers buyer activity (by completed order count; GMV hidden)
|
|
1289
|
-
- verifiers verifier board (correct count / accuracy)
|
|
1290
|
-
- arbitrators arbitrator reputation (fairness_score)
|
|
1291
|
-
- agents agent eval (trust_score + 30d call count)
|
|
1129
|
+
// was ~817 chars, now ~480 chars
|
|
1130
|
+
description: `WebAZ leaderboards — no centralized traffic distribution, pure real-signal ranking. **Privacy-first**: GMV / revenue amounts NEVER exposed.
|
|
1292
1131
|
|
|
1293
|
-
|
|
1294
|
-
|
|
1132
|
+
8 kinds:
|
|
1133
|
+
- products (sales×0.5 + referrals×2.0 + likes×1.0)
|
|
1134
|
+
- value_products (💎 cheapest 20% per category, daily batch)
|
|
1135
|
+
- creators (total likes received)
|
|
1136
|
+
- sellers (rating × log(reviews+1); GMV hidden)
|
|
1137
|
+
- buyers (completed order count; GMV hidden)
|
|
1138
|
+
- verifiers (correct count / accuracy)
|
|
1139
|
+
- arbitrators (fairness_score)
|
|
1140
|
+
- agents (trust_score + 30d call count)`,
|
|
1295
1141
|
inputSchema: {
|
|
1296
1142
|
type: 'object',
|
|
1297
1143
|
properties: {
|
|
1298
1144
|
kind: {
|
|
1299
1145
|
type: 'string',
|
|
1300
1146
|
enum: ['products', 'value_products', 'creators', 'sellers', 'buyers', 'verifiers', 'arbitrators', 'agents'],
|
|
1301
|
-
description: '
|
|
1147
|
+
description: 'Leaderboard kind',
|
|
1302
1148
|
},
|
|
1303
|
-
limit: { type: 'number', description: '
|
|
1149
|
+
limit: { type: 'number', description: 'Default 20, max 50' },
|
|
1304
1150
|
},
|
|
1305
1151
|
required: ['kind'],
|
|
1306
1152
|
},
|
|
1307
1153
|
},
|
|
1308
1154
|
{
|
|
1309
1155
|
name: 'webaz_auction',
|
|
1310
|
-
|
|
1156
|
+
// was ~967 chars, now ~550 chars
|
|
1157
|
+
description: `English forward auction — seller posts → buyers raise → **anti-sniping extension** → highest wins.
|
|
1311
1158
|
|
|
1312
|
-
USE THIS
|
|
1313
|
-
collectibles, price-discovery). NOT a regular product search — auctions are time-windowed events.
|
|
1314
|
-
For fixed-price items use webaz_search.
|
|
1315
|
-
Actions:
|
|
1316
|
-
- create (seller): start auction; needs title/qty/category/starting_price, optional min_increment/reserve_price/window_min/sniper_extend_min
|
|
1317
|
-
- browse: public board
|
|
1318
|
-
- mine: my created (seller) + my participated (buyer)
|
|
1319
|
-
- detail: full detail incl. bid history (buyer_id redacted for non-seller / non-bidder viewers)
|
|
1320
|
-
- bid (buyer): place bid; needs auction_id + price (first ≥ starting; subsequent ≥ current + increment)
|
|
1321
|
-
- cancel (seller): cancel (only before any bid placed)
|
|
1159
|
+
USE THIS to BID on auction items OR seller starts auction (rare goods / collectibles / price-discovery). NOT regular product search — auctions are **time-windowed events**. For fixed-price use webaz_search.
|
|
1322
1160
|
|
|
1323
|
-
|
|
1324
|
-
|
|
1161
|
+
Actions:
|
|
1162
|
+
- create (seller): title/qty/category/starting_price + optional min_increment/reserve_price/window_min/sniper_extend_min
|
|
1163
|
+
- browse / mine (own + participated) / detail (bid history; buyer_id redacted to non-seller/non-bidder)
|
|
1164
|
+
- bid (buyer): auction_id + price (first ≥ starting; next ≥ current + increment)
|
|
1165
|
+
- cancel (seller, only pre-bid)`,
|
|
1325
1166
|
inputSchema: {
|
|
1326
1167
|
type: 'object',
|
|
1327
1168
|
properties: {
|
|
@@ -1344,16 +1185,12 @@ Actions:
|
|
|
1344
1185
|
},
|
|
1345
1186
|
{
|
|
1346
1187
|
name: 'webaz_auto_bid',
|
|
1188
|
+
// was ~595 chars, now ~340 chars
|
|
1347
1189
|
description: `Seller auto_bid Skill config — auto-quote on RFQ creation instantly.
|
|
1348
1190
|
|
|
1349
|
-
|
|
1350
|
-
Actions:
|
|
1351
|
-
- get: read current Skill config
|
|
1352
|
-
- set: create/update Skill (needs categories[] / regions[] / max_eta_h / bid_strategy etc.)
|
|
1353
|
-
- disable: one-click disable (keeps config)
|
|
1191
|
+
Shortcut for \`webaz_skill install kind=auto_bid\` + ongoing config edits. Dedicated tool because auto_bid is most-used + needs frequent tuning (max_eta_h / undercut_pct / daily_cap). For other Skill kinds use webaz_skill.
|
|
1354
1192
|
|
|
1355
|
-
|
|
1356
|
-
中文:卖家 auto_bid Skill — RFQ 创建瞬间自动报价。Actions: get / set / disable。`,
|
|
1193
|
+
Actions: get | set (categories[] / regions[] / max_eta_h / bid_strategy) | disable (keeps config).`,
|
|
1357
1194
|
inputSchema: {
|
|
1358
1195
|
type: 'object',
|
|
1359
1196
|
properties: {
|
|
@@ -1364,7 +1201,7 @@ Actions:
|
|
|
1364
1201
|
max_eta_h: { type: 'number' },
|
|
1365
1202
|
fulfillment_type: { type: 'string', enum: ['instant_pickup', 'same_day', 'next_day', 'standard'] },
|
|
1366
1203
|
bid_strategy: { type: 'string', enum: ['cheapest_undercut', 'match_budget'] },
|
|
1367
|
-
undercut_pct: { type: 'number', description: '0–0.5
|
|
1204
|
+
undercut_pct: { type: 'number', description: '0–0.5; undercut margin' },
|
|
1368
1205
|
max_price_cap: { type: 'number' },
|
|
1369
1206
|
daily_cap: { type: 'number' },
|
|
1370
1207
|
cooldown_min: { type: 'number' },
|
|
@@ -1375,151 +1212,249 @@ Actions:
|
|
|
1375
1212
|
},
|
|
1376
1213
|
{
|
|
1377
1214
|
name: 'webaz_skill_market',
|
|
1378
|
-
|
|
1215
|
+
// was ~1426 chars, now ~720 chars
|
|
1216
|
+
description: `Knowledge-skill marketplace — anyone publishes content skills (templates / prompts / guides / checklists); others pay to unlock.
|
|
1379
1217
|
|
|
1380
|
-
|
|
1381
|
-
Billing modes: free / one_time (buy once, permanent) / per_use (charged each read).
|
|
1382
|
-
Revenue is an independent flow (author net → wallet, 5% protocol fee → sys_protocol); it does NOT enter PV / referral commission engines.
|
|
1218
|
+
⚠️ **DISTINCT from webaz_skill** (which is seller behaviour-automation plugins, totally separate revenue flow).
|
|
1383
1219
|
|
|
1384
|
-
|
|
1385
|
-
- list browse listed skills (filters: kind / billing / query; no auth needed)
|
|
1386
|
-
- detail one skill's public detail (skill_id; content is NOT included)
|
|
1387
|
-
- publish publish a new skill (title + content + billing_mode required) → enters review queue
|
|
1388
|
-
- update edit own skill (editing an approved one re-enters review)
|
|
1389
|
-
- delist take own skill offline
|
|
1390
|
-
- resubmit resubmit a rejected/delisted skill for review
|
|
1391
|
-
- purchase unlock free / one_time skill (cannot buy your own)
|
|
1392
|
-
- read read the unlocked content; per_use charges price each call
|
|
1393
|
-
- my_skills my published skills (all statuses)
|
|
1394
|
-
- library my unlocked / used skills
|
|
1220
|
+
Lifecycle: publish → human admin content review (NOT via MCP) → listed → buyers unlock.
|
|
1395
1221
|
|
|
1396
|
-
|
|
1397
|
-
|
|
1222
|
+
Billing: \`free\` | \`one_time\` (buy once, permanent) | \`per_use\` (charged each read).
|
|
1223
|
+
|
|
1224
|
+
⚠️ **Revenue is independent flow**: author net → wallet, 5% protocol fee → sys_protocol. Does **NOT** enter PV / referral commission engines.
|
|
1225
|
+
|
|
1226
|
+
Actions: list (no auth, filters: kind/billing/query) | detail (public, no content) | publish (→ review queue) | update (re-enters review if approved) | delist | resubmit | purchase (free / one_time; cannot self-buy) | read (per_use charges each call) | my_skills | library.`,
|
|
1398
1227
|
inputSchema: {
|
|
1399
1228
|
type: 'object',
|
|
1400
1229
|
properties: {
|
|
1401
|
-
api_key: { type: 'string', description: '
|
|
1230
|
+
api_key: { type: 'string', description: 'Your api_key (omit for list/detail)' },
|
|
1402
1231
|
action: {
|
|
1403
1232
|
type: 'string',
|
|
1404
1233
|
enum: ['list', 'detail', 'publish', 'update', 'delist', 'resubmit', 'purchase', 'read', 'my_skills', 'library'],
|
|
1405
|
-
description: '
|
|
1234
|
+
description: 'Action to execute',
|
|
1406
1235
|
},
|
|
1407
|
-
skill_id: { type: 'string', description: '
|
|
1236
|
+
skill_id: { type: 'string', description: 'Skill ID (required for detail/update/delist/resubmit/purchase/read)' },
|
|
1408
1237
|
// publish / update
|
|
1409
|
-
title: { type: 'string', description: '
|
|
1410
|
-
content: { type: 'string', description: '
|
|
1411
|
-
summary: { type: 'string', description: '
|
|
1412
|
-
preview: { type: 'string', description: '
|
|
1413
|
-
skill_kind: { type: 'string', enum: ['template', 'prompt', 'guide', 'checklist'], description: '
|
|
1414
|
-
billing_mode: { type: 'string', enum: ['free', 'one_time', 'per_use'], description: '
|
|
1415
|
-
price: { type: 'number', description: 'WAZ
|
|
1416
|
-
category: { type: 'string', description: '
|
|
1238
|
+
title: { type: 'string', description: 'Title (required for publish)' },
|
|
1239
|
+
content: { type: 'string', description: 'Skill content, visible only after purchase (required for publish)' },
|
|
1240
|
+
summary: { type: 'string', description: 'One-line summary (optional)' },
|
|
1241
|
+
preview: { type: 'string', description: 'Public preview, visible without purchase (optional)' },
|
|
1242
|
+
skill_kind: { type: 'string', enum: ['template', 'prompt', 'guide', 'checklist'], description: 'Skill kind (default template)' },
|
|
1243
|
+
billing_mode: { type: 'string', enum: ['free', 'one_time', 'per_use'], description: 'Billing mode (required for publish)' },
|
|
1244
|
+
price: { type: 'number', description: 'Price in WAZ; free must = 0, paid must > 0, max 100000' },
|
|
1245
|
+
category: { type: 'string', description: 'Category (optional)' },
|
|
1417
1246
|
// list filters
|
|
1418
|
-
kind: { type: 'string', enum: ['template', 'prompt', 'guide', 'checklist'], description: '
|
|
1419
|
-
billing: { type: 'string', enum: ['free', 'one_time', 'per_use'], description: '
|
|
1420
|
-
query: { type: 'string', description: '
|
|
1247
|
+
kind: { type: 'string', enum: ['template', 'prompt', 'guide', 'checklist'], description: 'Filter type (optional for list)' },
|
|
1248
|
+
billing: { type: 'string', enum: ['free', 'one_time', 'per_use'], description: 'Filter billing mode (optional for list)' },
|
|
1249
|
+
query: { type: 'string', description: 'Keyword search (optional for list)' },
|
|
1421
1250
|
},
|
|
1422
1251
|
required: ['action'],
|
|
1423
1252
|
},
|
|
1424
1253
|
},
|
|
1425
1254
|
{
|
|
1426
1255
|
name: 'webaz_secondhand',
|
|
1427
|
-
|
|
1256
|
+
// was ~1285 chars, now ~650 chars
|
|
1257
|
+
description: `Secondhand market (个人闲置二手) — P2P pre-owned goods, 1% protocol fee, escrow-protected. Supports shipping + in-person handoff.
|
|
1428
1258
|
|
|
1429
|
-
USE THIS
|
|
1430
|
-
For NEW manufactured products use webaz_search. Note: secondhand and shop catalog are separate
|
|
1431
|
-
spaces — webaz_search does NOT return secondhand listings.
|
|
1432
|
-
|
|
1433
|
-
Actions:
|
|
1434
|
-
- browse list available items (filters: category / condition / region / min_price / max_price / query / sort; no auth needed; excludes your own when api_key given)
|
|
1435
|
-
- detail one item's detail + seller's other listings (item_id; no auth needed)
|
|
1436
|
-
- publish list an item (title + category + condition + price + images[] required; ≥1 image)
|
|
1437
|
-
- update edit own item (item_id + fields; can set status available/reserved/closed)
|
|
1438
|
-
- mine my listings + stats (available/sold/earned)
|
|
1439
|
-
- buy place an order on an item (item_id + fulfillment_mode; shipping needs shipping_address)
|
|
1259
|
+
USE THIS for USED / pre-owned / 闲置 / 二手 items, OR selling own used. NOT for NEW manufactured (use webaz_search). **Separate space** — webaz_search does NOT return secondhand listings.
|
|
1440
1260
|
|
|
1441
|
-
|
|
1442
|
-
condition: brand_new / like_new / lightly_used / well_used / heavily_used
|
|
1443
|
-
fulfillment: shipping / in_person / both
|
|
1261
|
+
Actions: browse (filters: category/condition/region/price/query/sort; no auth, excludes own when api_key given) | detail (no auth) | publish (title + category + condition + price + images[≥1]) | update (item_id + fields; status available/reserved/closed) | mine | buy (item_id + fulfillment_mode; shipping needs shipping_address).
|
|
1444
1262
|
|
|
1445
|
-
|
|
1446
|
-
中文:二手集市 — 个人闲置 P2P,协议费 1%,escrow 保护,支持快递/面交。Actions: browse / detail / publish / update / mine / buy。`,
|
|
1263
|
+
Enums: **category** phone/computer/appliance/furniture/clothing/book/toy/sports/other · **condition** brand_new/like_new/lightly_used/well_used/heavily_used · **fulfillment** shipping/in_person/both.`,
|
|
1447
1264
|
inputSchema: {
|
|
1448
1265
|
type: 'object',
|
|
1449
1266
|
properties: {
|
|
1450
|
-
api_key: { type: 'string', description: '
|
|
1451
|
-
action: { type: 'string', enum: ['browse', 'detail', 'publish', 'update', 'mine', 'buy'], description: '
|
|
1452
|
-
item_id: { type: 'string', description: '
|
|
1267
|
+
api_key: { type: 'string', description: 'Your api_key (omit for browse/detail)' },
|
|
1268
|
+
action: { type: 'string', enum: ['browse', 'detail', 'publish', 'update', 'mine', 'buy'], description: 'Action to execute' },
|
|
1269
|
+
item_id: { type: 'string', description: 'Item ID (required for detail/update/buy)' },
|
|
1453
1270
|
// publish / update
|
|
1454
|
-
title: { type: 'string', description: '
|
|
1455
|
-
description: { type: 'string', description: '
|
|
1456
|
-
category: { type: 'string', enum: ['phone', 'computer', 'appliance', 'furniture', 'clothing', 'book', 'toy', 'sports', 'other'], description: '
|
|
1457
|
-
condition_grade: { type: 'string', enum: ['brand_new', 'like_new', 'lightly_used', 'well_used', 'heavily_used'], description: '
|
|
1458
|
-
price: { type: 'number', description: 'WAZ
|
|
1459
|
-
negotiable: { type: 'boolean', description: '
|
|
1460
|
-
images: { type: 'array', items: { type: 'string' }, description: '
|
|
1461
|
-
region: { type: 'string', description: '
|
|
1462
|
-
fulfillment: { type: 'string', enum: ['shipping', 'in_person', 'both'], description: '
|
|
1463
|
-
status: { type: 'string', enum: ['available', 'reserved', 'closed'], description: '
|
|
1271
|
+
title: { type: 'string', description: 'Title 2-60 chars (required for publish)' },
|
|
1272
|
+
description: { type: 'string', description: 'Description (≤1000 chars, optional)' },
|
|
1273
|
+
category: { type: 'string', enum: ['phone', 'computer', 'appliance', 'furniture', 'clothing', 'book', 'toy', 'sports', 'other'], description: 'Category (required for publish)' },
|
|
1274
|
+
condition_grade: { type: 'string', enum: ['brand_new', 'like_new', 'lightly_used', 'well_used', 'heavily_used'], description: 'Condition grade (required for publish)' },
|
|
1275
|
+
price: { type: 'number', description: 'Price in WAZ 0-100000 (required for publish)' },
|
|
1276
|
+
negotiable: { type: 'boolean', description: 'Negotiable flag (optional)' },
|
|
1277
|
+
images: { type: 'array', items: { type: 'string' }, description: 'Images dataURL/URL array, ≥1 ≤9 (required for publish)' },
|
|
1278
|
+
region: { type: 'string', description: 'Region (≤40 chars, optional)' },
|
|
1279
|
+
fulfillment: { type: 'string', enum: ['shipping', 'in_person', 'both'], description: 'Fulfillment (default both)' },
|
|
1280
|
+
status: { type: 'string', enum: ['available', 'reserved', 'closed'], description: 'Change status (optional for update)' },
|
|
1464
1281
|
// buy
|
|
1465
|
-
fulfillment_mode: { type: 'string', enum: ['shipping', 'in_person'], description: '
|
|
1466
|
-
shipping_address: { type: 'string', description: '
|
|
1467
|
-
notes: { type: 'string', description: '
|
|
1282
|
+
fulfillment_mode: { type: 'string', enum: ['shipping', 'in_person'], description: 'Per-order fulfillment (required for buy, default shipping)' },
|
|
1283
|
+
shipping_address: { type: 'string', description: 'Shipping address (required for buy + shipping)' },
|
|
1284
|
+
notes: { type: 'string', description: 'Order note (optional for buy; can include counter-offer)' },
|
|
1468
1285
|
// browse filters
|
|
1469
|
-
condition: { type: 'string', description: '
|
|
1286
|
+
condition: { type: 'string', description: 'Filter condition, comma-separated multi (optional for browse)' },
|
|
1470
1287
|
min_price: { type: 'number' },
|
|
1471
1288
|
max_price: { type: 'number' },
|
|
1472
|
-
query: { type: 'string', description: '
|
|
1473
|
-
sort: { type: 'string', enum: ['newest', 'price_asc', 'price_desc', 'popular'], description: '
|
|
1289
|
+
query: { type: 'string', description: 'Keyword (optional for browse)' },
|
|
1290
|
+
sort: { type: 'string', enum: ['newest', 'price_asc', 'price_desc', 'popular'], description: 'Sort (optional for browse)' },
|
|
1474
1291
|
},
|
|
1475
1292
|
required: ['action'],
|
|
1476
1293
|
},
|
|
1477
1294
|
},
|
|
1478
1295
|
{
|
|
1479
1296
|
name: 'webaz_trial',
|
|
1480
|
-
|
|
1297
|
+
// was ~1506 chars, now ~720 chars
|
|
1298
|
+
description: `Trial-for-review (测评免单) — seller refunds buyer's order when buyer posts qualifying review note that reaches a view threshold.
|
|
1481
1299
|
|
|
1482
|
-
USE THIS when:
|
|
1483
|
-
- buyer asks "is there a trial / free-test / 测评免单 / 0 元试用 for this product?", OR
|
|
1484
|
-
- buyer has already ordered a product with a trial campaign and wants to claim the slot, OR
|
|
1485
|
-
- seller wants to launch a trial campaign to seed reviews.
|
|
1486
|
-
NOT a search tool — for product discovery use webaz_search (can filter by has_trial=true coming soon).
|
|
1300
|
+
USE THIS when: buyer asks "trial / 测评免单 / 0 元试用 for this product?" | buyer has ordered product with active campaign + wants to claim | seller wants to launch campaign. NOT a search tool — use webaz_search.
|
|
1487
1301
|
|
|
1488
|
-
Anti-abuse
|
|
1302
|
+
⚠️ **Anti-abuse enforced server-side** (MCP just passes through): buyer ≠ seller / must have confirmed-or-completed order / account age ≥3d / IP+UA rate limits / config snapshot at claim time.
|
|
1489
1303
|
|
|
1490
1304
|
Buyer actions:
|
|
1491
|
-
- get_campaign
|
|
1492
|
-
- apply
|
|
1493
|
-
- link_note
|
|
1494
|
-
- my_claims
|
|
1495
|
-
Seller actions:
|
|
1496
|
-
- create_campaign open/update a campaign on your product (product_id + quota_total + reach_threshold + min_chars + min_days_live)
|
|
1497
|
-
- cancel_campaign close your product's campaign (product_id)
|
|
1498
|
-
- my_campaigns my seller-side campaigns
|
|
1499
|
-
- campaign_claims claims under a campaign (campaign_id)
|
|
1305
|
+
- get_campaign read product's active campaign (no auth)
|
|
1306
|
+
- apply claim slot (product_id)
|
|
1307
|
+
- link_note attach review note (claim_id + note_id; note must be type=note + bound to product + active)
|
|
1308
|
+
- my_claims my claims + statuses
|
|
1500
1309
|
|
|
1501
|
-
|
|
1502
|
-
|
|
1310
|
+
Seller actions:
|
|
1311
|
+
- create_campaign open/update (quota_total 1-200 + reach_threshold 10-10000 + min_chars 20-5000 + min_days_live 1-90)
|
|
1312
|
+
- cancel_campaign / my_campaigns / campaign_claims`,
|
|
1503
1313
|
inputSchema: {
|
|
1504
1314
|
type: 'object',
|
|
1505
1315
|
properties: {
|
|
1506
|
-
api_key: { type: 'string', description: '
|
|
1507
|
-
action: { type: 'string', enum: ['get_campaign', 'apply', 'link_note', 'my_claims', 'create_campaign', 'cancel_campaign', 'my_campaigns', 'campaign_claims'], description: '
|
|
1508
|
-
product_id: { type: 'string', description: '
|
|
1509
|
-
claim_id: { type: 'string', description: '
|
|
1510
|
-
campaign_id: { type: 'string', description: '
|
|
1511
|
-
note_id: { type: 'string', description: '
|
|
1316
|
+
api_key: { type: 'string', description: 'Your api_key (omit for get_campaign)' },
|
|
1317
|
+
action: { type: 'string', enum: ['get_campaign', 'apply', 'link_note', 'my_claims', 'create_campaign', 'cancel_campaign', 'my_campaigns', 'campaign_claims'], description: 'Action to execute' },
|
|
1318
|
+
product_id: { type: 'string', description: 'Product ID (required for get_campaign/apply/create_campaign/cancel_campaign)' },
|
|
1319
|
+
claim_id: { type: 'string', description: 'Claim ID (required for link_note)' },
|
|
1320
|
+
campaign_id: { type: 'string', description: 'Campaign ID (required for campaign_claims)' },
|
|
1321
|
+
note_id: { type: 'string', description: 'Review note ID (required for link_note; must be type=note + bound to product + active)' },
|
|
1512
1322
|
// create_campaign config
|
|
1513
|
-
quota_total: { type: 'number', description: '
|
|
1514
|
-
reach_threshold: { type: 'number', description: '
|
|
1515
|
-
min_chars: { type: 'number', description: '
|
|
1516
|
-
min_days_live: { type: 'number', description: '
|
|
1323
|
+
quota_total: { type: 'number', description: 'Quota total 1-200 (required for create_campaign)' },
|
|
1324
|
+
reach_threshold: { type: 'number', description: 'Reach threshold 10-10000 (default 50)' },
|
|
1325
|
+
min_chars: { type: 'number', description: 'Min note chars 20-5000 (default 50)' },
|
|
1326
|
+
min_days_live: { type: 'number', description: 'Min note alive days 1-90 (default 7)' },
|
|
1517
1327
|
},
|
|
1518
1328
|
required: ['action'],
|
|
1519
1329
|
},
|
|
1520
1330
|
},
|
|
1331
|
+
{
|
|
1332
|
+
name: 'webaz_feedback',
|
|
1333
|
+
description: `Submit the user's in-use feedback about WebAZ itself, where it happens — agent-native "use→build" 用→建. Hit a problem or have an idea? Call this instead of "go file a GitHub issue". Auto-attaches the redacted **scene** (your recent calls+outcomes) so a maintainer can reproduce.
|
|
1334
|
+
|
|
1335
|
+
Actions:
|
|
1336
|
+
- submit (default): type=ux_issue|bug|proposal, area (search/order/dispute…), text, severity=low|annoying|blocking (issues), opt. subject → id+status
|
|
1337
|
+
- my: your past feedback + status (received→triaged→in_progress→resolved/declined/duplicate); accepted → co-build reputation
|
|
1338
|
+
- get: one by id
|
|
1339
|
+
|
|
1340
|
+
Gate by type: ux_issue/bug (reporting = using) → login only, NO Passkey, anyone reports. proposal (building) → Passkey real-person (reward anchor; credited only to Passkey submitters). NETWORK only.`,
|
|
1341
|
+
inputSchema: {
|
|
1342
|
+
type: 'object',
|
|
1343
|
+
properties: {
|
|
1344
|
+
action: { type: 'string', enum: ['submit', 'my', 'get'], description: 'submit (default) | my | get' },
|
|
1345
|
+
api_key: { type: 'string', description: "User's api_key (real person required)" },
|
|
1346
|
+
type: { type: 'string', enum: ['ux_issue', 'bug', 'proposal'], description: 'submit: kind of feedback' },
|
|
1347
|
+
area: { type: 'string', description: 'submit: which feature, e.g. search / order / dispute' },
|
|
1348
|
+
severity: { type: 'string', enum: ['low', 'annoying', 'blocking'], description: 'submit: for ux_issue/bug' },
|
|
1349
|
+
subject: { type: 'string', description: 'submit: optional short title' },
|
|
1350
|
+
text: { type: 'string', description: 'submit: the feedback / idea (≥5 chars)' },
|
|
1351
|
+
feedback_id: { type: 'string', description: 'get: the feedback id' },
|
|
1352
|
+
},
|
|
1353
|
+
required: ['api_key'],
|
|
1354
|
+
},
|
|
1355
|
+
},
|
|
1356
|
+
{
|
|
1357
|
+
name: 'webaz_contribute',
|
|
1358
|
+
description: `Coordinate building WebAZ itself (RFC-006) — a claim board so contributors don't collide. Check BEFORE starting work on an area. Day-to-day small changes; large ones go via RFC. 协调"谁在做什么"防撞车.
|
|
1359
|
+
|
|
1360
|
+
Actions:
|
|
1361
|
+
- list_open (default): open tasks (opt. area filter)
|
|
1362
|
+
- claim: take an open task; provenance=human|ai_assisted|ai_authored (self-declared, not detected); auto-expires ~7d if not submitted
|
|
1363
|
+
- submit: mark in_review with pr_ref
|
|
1364
|
+
- status: tasks you hold (claimed/in_review)
|
|
1365
|
+
- profile: your build dashboard — KPI/tier/restrictions+appeal, self-view (private, no public leaderboard)
|
|
1366
|
+
|
|
1367
|
+
Coordinates + records only — NO merge/reward; acceptance (done) = human maintainer. build_reputation is a SEPARATE pool, never gates verifier/arbitrator. Login required; NETWORK only.`,
|
|
1368
|
+
inputSchema: {
|
|
1369
|
+
type: 'object',
|
|
1370
|
+
properties: {
|
|
1371
|
+
action: { type: 'string', enum: ['list_open', 'claim', 'submit', 'status', 'profile'], description: 'list_open (default) | claim | submit | status | profile' },
|
|
1372
|
+
api_key: { type: 'string', description: "User's api_key (accountable identity)" },
|
|
1373
|
+
task_id: { type: 'string', description: 'claim / submit: the task id' },
|
|
1374
|
+
area: { type: 'string', description: 'list_open: optional area filter (e.g. search / docs / mcp)' },
|
|
1375
|
+
provenance: { type: 'string', enum: ['human', 'ai_assisted', 'ai_authored'], description: 'claim: self-declared authorship (default human)' },
|
|
1376
|
+
pr_ref: { type: 'string', description: 'submit: your PR link or number' },
|
|
1377
|
+
note: { type: 'string', description: 'submit: optional note' },
|
|
1378
|
+
},
|
|
1379
|
+
required: ['api_key'],
|
|
1380
|
+
},
|
|
1381
|
+
},
|
|
1521
1382
|
];
|
|
1522
1383
|
// ─── 工具处理函数 ─────────────────────────────────────────────
|
|
1384
|
+
// RFC-004: webaz_feedback — agent-native "use → build" 反馈(双模;仅 NETWORK 能送达)
|
|
1385
|
+
async function handleFeedback(args) {
|
|
1386
|
+
const action = args.action || 'submit';
|
|
1387
|
+
const apiKey = args.api_key;
|
|
1388
|
+
if (!apiKey)
|
|
1389
|
+
return { error: 'api_key required' };
|
|
1390
|
+
if (toolBackend('webaz_feedback') !== 'network') {
|
|
1391
|
+
return {
|
|
1392
|
+
_mode: 'sandbox',
|
|
1393
|
+
error: 'SANDBOX 模式下反馈无人接收 —— 建设性反馈要进真实项目才有意义。请设 WEBAZ_API_KEY 切到 NETWORK 模式后再提交。 / Feedback needs NETWORK mode to reach the project; set WEBAZ_API_KEY.',
|
|
1394
|
+
error_code: 'FEEDBACK_NEEDS_NETWORK',
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
if (action === 'my')
|
|
1398
|
+
return apiCall('/api/build-feedback/mine', { apiKey });
|
|
1399
|
+
if (action === 'get') {
|
|
1400
|
+
const fid = args.feedback_id;
|
|
1401
|
+
if (!fid)
|
|
1402
|
+
return { error: 'feedback_id required for action=get' };
|
|
1403
|
+
return apiCall('/api/build-feedback/' + encodeURIComponent(fid), { apiKey });
|
|
1404
|
+
}
|
|
1405
|
+
// submit(默认)
|
|
1406
|
+
const text = (args.text ?? '').trim();
|
|
1407
|
+
if (text.length < 5)
|
|
1408
|
+
return { error: 'text required (≥5 chars)' };
|
|
1409
|
+
return apiCall('/api/build-feedback', {
|
|
1410
|
+
method: 'POST', apiKey,
|
|
1411
|
+
body: {
|
|
1412
|
+
type: args.type || 'ux_issue',
|
|
1413
|
+
area: args.area,
|
|
1414
|
+
severity: args.severity,
|
|
1415
|
+
subject: args.subject,
|
|
1416
|
+
text,
|
|
1417
|
+
scene: recentCalls.slice(-8), // 现场证据:脱敏摘要(tool / arg_keys / outcome / mode)
|
|
1418
|
+
},
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
// RFC-006 Gap 1: webaz_contribute — 协调"谁在做什么"(双模;仅 NETWORK)
|
|
1422
|
+
async function handleContribute(args) {
|
|
1423
|
+
const action = args.action || 'list_open';
|
|
1424
|
+
const apiKey = args.api_key;
|
|
1425
|
+
if (!apiKey)
|
|
1426
|
+
return { error: 'api_key required' };
|
|
1427
|
+
if (toolBackend('webaz_contribute') !== 'network') {
|
|
1428
|
+
return {
|
|
1429
|
+
_mode: 'sandbox',
|
|
1430
|
+
error: 'SANDBOX 模式无协调对象 —— 协调要在真实项目上才有意义。请设 WEBAZ_API_KEY 切到 NETWORK 模式。 / Coordination needs NETWORK mode; set WEBAZ_API_KEY.',
|
|
1431
|
+
error_code: 'CONTRIBUTE_NEEDS_NETWORK',
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
if (action === 'status')
|
|
1435
|
+
return apiCall('/api/build-tasks?mine=1', { apiKey });
|
|
1436
|
+
if (action === 'profile')
|
|
1437
|
+
return apiCall('/api/build-reputation/me', { apiKey });
|
|
1438
|
+
if (action === 'claim') {
|
|
1439
|
+
const tid = args.task_id;
|
|
1440
|
+
if (!tid)
|
|
1441
|
+
return { error: 'task_id required for action=claim' };
|
|
1442
|
+
return apiCall('/api/build-tasks/' + encodeURIComponent(tid) + '/claim', {
|
|
1443
|
+
method: 'POST', apiKey, body: { provenance: args.provenance },
|
|
1444
|
+
});
|
|
1445
|
+
}
|
|
1446
|
+
if (action === 'submit') {
|
|
1447
|
+
const tid = args.task_id;
|
|
1448
|
+
if (!tid)
|
|
1449
|
+
return { error: 'task_id required for action=submit' };
|
|
1450
|
+
return apiCall('/api/build-tasks/' + encodeURIComponent(tid) + '/submit', {
|
|
1451
|
+
method: 'POST', apiKey, body: { pr_ref: args.pr_ref, note: args.note },
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
// list_open(默认)
|
|
1455
|
+
const q = args.area ? '?status=open&area=' + encodeURIComponent(String(args.area)) : '?status=open';
|
|
1456
|
+
return apiCall('/api/build-tasks' + q, { apiKey });
|
|
1457
|
+
}
|
|
1523
1458
|
function handleInfo() {
|
|
1524
1459
|
const summary = getManifestSummary();
|
|
1525
1460
|
// QA 轮 3 抓到:live_stats 不是 hardcoded、不是 remote — 就是本地 SQLite count。这里加 source 字段澄清。
|
|
@@ -1560,13 +1495,26 @@ function handleInfo() {
|
|
|
1560
1495
|
// 第三方尽调 agent 抓到过的破绽:live_stats 是本地库数字、引导词推 agent 拉新、佣金结构有 MLM 形态。
|
|
1561
1496
|
// 此处主动披露,不抗辩;agent 自己判断如何处理。
|
|
1562
1497
|
network_state: {
|
|
1498
|
+
// RFC-003 P3:显式声明当前客户端模式,让 agent 一眼分清"真网络 vs 本机沙盒"
|
|
1499
|
+
mode: MODE, // 'network' | 'sandbox'
|
|
1500
|
+
mode_banner: modeBanner(),
|
|
1501
|
+
mode_meaning: MODE === 'network'
|
|
1502
|
+
? '🟢 NETWORK:核心交易工具(下单/上架/履约/比价等)走 webaz.xyz 共享生产网络。注意:本 webaz_info 工具尚未联网,下方 live_stats 仍读本机本地缓存,不代表全网规模。'
|
|
1503
|
+
: '🟡 SANDBOX:所有工具都在本机本地 SQLite 运行,与 webaz.xyz 全网隔离。任何计数 / 账号 / 订单仅本机有效,不是真实网络状态。设 WEBAZ_API_KEY 可切到 NETWORK。',
|
|
1563
1504
|
phase: 'pre_launch',
|
|
1564
1505
|
real_users_on_canonical: 0,
|
|
1565
1506
|
canonical_endpoint: 'https://webaz.xyz',
|
|
1566
1507
|
economic_flow: 'simulated WAZ (test currency, 1 WAZ ≈ 1 USDC peg is a模拟基准, not a real exchange rate). No fiat/crypto settles yet.',
|
|
1567
1508
|
disclaimer: '本协议尚未公开上线,prod 真实用户≈0,无真实经济流转。下方 live_stats / 工具示例所有计数均来自**本机 MCP 服务器的本地 SQLite**(~/.webaz/webaz.db),仅供 dev / demo,不代表协议全网真实状态。请勿据此评估市场规模、做投资决策、或替终端用户承诺任何经济关系。',
|
|
1568
1509
|
},
|
|
1569
|
-
description: 'WebAZ
|
|
1510
|
+
description: 'WebAZ is a decentralized commerce protocol. Every transaction flows through a state machine; each state transition needs proof-of-action from the responsible party. Any timeout-without-action: protocol auto-rules default + executes remedy. / WebAZ 是去中心化商业协议;每笔交易通过状态机流转,每次状态转移需对应责任方的操作证明;超时未操作则协议自动判违约并执行处置。',
|
|
1511
|
+
// 连接两个场景:用协议(本工具) ↔ 改协议(开发协作)。想改 WebAZ 本身的 agent 从这里进。
|
|
1512
|
+
for_contributors: {
|
|
1513
|
+
note: 'Want to change WebAZ itself (not just use it)? This is an open, agent-native protocol — AI-authored PRs are welcome, with accountability. / 想改 WebAZ 本身(不只是用)?这是开放的 agent 原生协议,欢迎 AI 提 PR,但需问责。',
|
|
1514
|
+
repo: 'https://github.com/seasonsagents-art/webaz',
|
|
1515
|
+
start_here: 'AGENTS.md (project map + before-you-code + PR flow) → CONTRIBUTING.md (full guide)',
|
|
1516
|
+
ai_accountability: 'AI-authored PRs: add 🤖🤖🤖 to the PR title; the agent must be triggered by a Passkey-bound human (webazer) who is accountable. / AI 提 PR:标题加 🤖🤖🤖,且须由已绑 Passkey 的真人(webazer)触发并担责。',
|
|
1517
|
+
},
|
|
1570
1518
|
live_stats: stats,
|
|
1571
1519
|
economics,
|
|
1572
1520
|
// QA 轮 14.c P1:显式归因机制(与传统 MLM 自动吃下线的根本区别)
|
|
@@ -1577,7 +1525,7 @@ function handleInfo() {
|
|
|
1577
1525
|
redirect_rules: 'chain_gap (无 L / sponsor 无效) → charity_fund; region cap (level > region max_levels) → global_fund. global region max_levels=1 (仅 L1);singapore 等 max_levels=3.',
|
|
1578
1526
|
l1_gate: 'promoter 必须是 verified buyer(≥1 笔完成订单)才能领 commission,否则该份 redirect。',
|
|
1579
1527
|
// 主动披露,不要让外部尽调 agent 自己读出来再写差评
|
|
1580
|
-
compliance_notice: '⚠️ 本协议含三级佣金(L1/L2/L3 7:2:1) + 二元配对树(binary PV matching) + 邀请链结构。这类形态在多数司法辖区可能与**多层级营销(MLM)的法律定义重叠**。本协议通过显式 per-order 归因(非自动吃下线)规避了 MLM 寡头化的核心病灶,但形态层面仍带 MLM 特征,我们诚实告知。**代理 AI
|
|
1528
|
+
compliance_notice: '⚠️ 本协议含三级佣金(L1/L2/L3 7:2:1) + 二元配对树(binary PV matching) + 邀请链结构。这类形态在多数司法辖区可能与**多层级营销(MLM)的法律定义重叠**。本协议通过显式 per-order 归因(非自动吃下线)规避了 MLM 寡头化的核心病灶,但形态层面仍带 MLM 特征,我们诚实告知。**代理 AI 不应默认替终端用户生成推广链接或拉新**——这需要用户的显式授权,且用户自身要先评估当地合规性。\n\n**Reward participation is opt-in (RFC-002)**: default = off. Users must apply (Passkey + ≥1 completed order); attribution always recorded (relation layer), but commission settlement gated until opt-in. Pending commission held in pending_commission_escrow for 30d grace. See docs/rfcs/RFC-002-rewards-opt-in.md for full state matrix.',
|
|
1581
1529
|
},
|
|
1582
1530
|
// QA 轮 3 FAIL:roles 漏 reviewer。register 工具支持 5 个角色,info 必须列全。
|
|
1583
1531
|
roles: {
|
|
@@ -1617,6 +1565,25 @@ function handleInfo() {
|
|
|
1617
1565
|
};
|
|
1618
1566
|
}
|
|
1619
1567
|
function handleRegister(args) {
|
|
1568
|
+
// ─── RFC-003 P3:NETWORK 模式不自助建号 ────────────────────────
|
|
1569
|
+
// 自助注册会绕过邀请码 / captcha / 责任制;且 CHARTER §4 I-5 要求账号必须由已绑 Passkey
|
|
1570
|
+
// 的真人创建("每个 agent 背后有可问责的真人")。NETWORK 模式下改为引导真人去 webaz.xyz 拿 key。
|
|
1571
|
+
if (MODE === 'network') {
|
|
1572
|
+
return {
|
|
1573
|
+
_mode: 'network',
|
|
1574
|
+
registration: 'must_be_done_by_human_at_webaz_xyz',
|
|
1575
|
+
message: '🟢 NETWORK 模式下不支持 agent 自助注册。开放协议的信任来自"每个 agent 背后有可问责的真人",所以注册这一步刻意留给真人在 webaz.xyz 完成。请按三步加入共享网络:',
|
|
1576
|
+
steps: [
|
|
1577
|
+
'1. 打开 https://webaz.xyz 注册账号(需邀请码;注册时绑定 Passkey 成为可问责真人)',
|
|
1578
|
+
'2. 进入「我的 / 设置」→ 复制你的 api_key',
|
|
1579
|
+
'3. 把 api_key 填入 MCP 配置环境变量 WEBAZ_API_KEY,重启 MCP —— 之后所有交易工具自动在 webaz.xyz 共享网络上操作',
|
|
1580
|
+
],
|
|
1581
|
+
register_url: WEBAZ_API_URL,
|
|
1582
|
+
why_not_agent_self_register: 'agent 自助注册会绕过邀请 / captcha / 真人 Passkey 责任制,破坏协议的可问责性(#6 不滥用 / CHARTER §4 I-5)。',
|
|
1583
|
+
want_to_try_offline_first: '只想离线试玩、暂不连网络?设环境变量 WEBAZ_MODE=sandbox(或清空 WEBAZ_API_KEY),webaz_register 会在本机沙盒建一个测试账号(仅本机有效)。',
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
// ─── SANDBOX 模式:本机建测试账号(显著标注,仅本机有效,与 webaz.xyz 全网隔离)──
|
|
1620
1587
|
const name = args.name;
|
|
1621
1588
|
const role = args.role;
|
|
1622
1589
|
const initialBalance = args.initial_balance ?? 1000;
|
|
@@ -1642,7 +1609,10 @@ function handleRegister(args) {
|
|
|
1642
1609
|
: '等待订单分配给你';
|
|
1643
1610
|
return {
|
|
1644
1611
|
success: true,
|
|
1645
|
-
|
|
1612
|
+
_mode: 'sandbox',
|
|
1613
|
+
sandbox_account: true,
|
|
1614
|
+
sandbox_warning: '⚠️ 这是 SANDBOX 测试账号 —— 仅本机有效,未在 webaz.xyz 全网注册,与共享网络完全隔离。要真正加入网络(让交易对其他人可见、形成网络效应),请在 https://webaz.xyz 注册并把 api_key 填入 WEBAZ_API_KEY 切到 NETWORK 模式。',
|
|
1615
|
+
message: '沙盒注册成功(仅本机)!妥善保管 api_key(身份凭证)+ permanent_code(恢复码,丢失 api_key 用它配 handle 找回)',
|
|
1646
1616
|
user_id: id,
|
|
1647
1617
|
api_key: apiKey,
|
|
1648
1618
|
permanent_code: permaCode,
|
|
@@ -1747,6 +1717,38 @@ async function handleSearch(args) {
|
|
|
1747
1717
|
if (limit > 200)
|
|
1748
1718
|
limit = 200;
|
|
1749
1719
|
const sortMode = args.sort ?? 'trending';
|
|
1720
|
+
// RFC-003 P4: NETWORK 模式关键词搜索 → 生产 GET /api/products?mode=agent
|
|
1721
|
+
// (同款协议级 strict alias 引擎,公开读,不传 fuzzy)。让 agent 搜到的是全网真实在售商品。
|
|
1722
|
+
if (toolBackend('webaz_search') === 'network') {
|
|
1723
|
+
const qs = new URLSearchParams({ mode: 'agent', limit: String(limit) });
|
|
1724
|
+
if (query)
|
|
1725
|
+
qs.set('q', query);
|
|
1726
|
+
if (category)
|
|
1727
|
+
qs.set('category', String(category));
|
|
1728
|
+
if (maxPrice != null)
|
|
1729
|
+
qs.set('max_price', String(maxPrice));
|
|
1730
|
+
if (minReturnDays != null)
|
|
1731
|
+
qs.set('min_return_days', String(minReturnDays));
|
|
1732
|
+
if (maxHandlingHours != null)
|
|
1733
|
+
qs.set('max_handling_hours', String(maxHandlingHours));
|
|
1734
|
+
if (hasSales)
|
|
1735
|
+
qs.set('has_sales', String(hasSales));
|
|
1736
|
+
if (sellerId)
|
|
1737
|
+
qs.set('seller_id', String(sellerId));
|
|
1738
|
+
if (args.sort)
|
|
1739
|
+
qs.set('sort', String(args.sort));
|
|
1740
|
+
const r = await apiCall('/api/products?' + qs.toString());
|
|
1741
|
+
if ('error' in r)
|
|
1742
|
+
return r;
|
|
1743
|
+
const products = r.products ?? [];
|
|
1744
|
+
return {
|
|
1745
|
+
...r,
|
|
1746
|
+
found: products.length,
|
|
1747
|
+
hint: products.length
|
|
1748
|
+
? `网络上匹配到 ${products.length} 件商品。下单前用 webaz_verify_price 锁价。`
|
|
1749
|
+
: '网络上未找到精确匹配商品(协议级 strict 匹配)。可换更准确的商品名,或用 paste_text 贴外链搜索。',
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1750
1752
|
let sql = `
|
|
1751
1753
|
SELECT p.*, u.name as seller_name,
|
|
1752
1754
|
COALESCE((SELECT total_points FROM reputation_scores WHERE user_id = p.seller_id), 0) as rep_points,
|
|
@@ -1919,7 +1921,15 @@ async function handleSearch(args) {
|
|
|
1919
1921
|
hint: 'agent 模式:products 已附带 metrics + score(含阶梯新鲜度 + 14d 首单 boost),可基于自身策略二次排序',
|
|
1920
1922
|
};
|
|
1921
1923
|
}
|
|
1922
|
-
function handleVerifyPrice(args) {
|
|
1924
|
+
async function handleVerifyPrice(args) {
|
|
1925
|
+
// RFC-003 P2: network 模式转发到生产 POST /api/verify-price(前置,绕过本地 db)
|
|
1926
|
+
if (toolBackend('webaz_verify_price') === 'network') {
|
|
1927
|
+
return apiCall('/api/verify-price', {
|
|
1928
|
+
method: 'POST',
|
|
1929
|
+
apiKey: args.api_key,
|
|
1930
|
+
body: { product_id: args.product_id, quantity: Number(args.quantity ?? 1) },
|
|
1931
|
+
});
|
|
1932
|
+
}
|
|
1923
1933
|
const auth = requireAuth(db, args.api_key);
|
|
1924
1934
|
if ('error' in auth)
|
|
1925
1935
|
return auth;
|
|
@@ -1969,6 +1979,56 @@ async function handleListProduct(args) {
|
|
|
1969
1979
|
const apiKey = args.api_key;
|
|
1970
1980
|
if (!apiKey)
|
|
1971
1981
|
return { error: 'api_key required' };
|
|
1982
|
+
// RFC-003 P2b: NETWORK 模式 — 卖家目录管理全部转发生产端点(单一真相源)
|
|
1983
|
+
if (toolBackend('webaz_list_product') === 'network') {
|
|
1984
|
+
const pid = args.product_id;
|
|
1985
|
+
if (action === 'mine') {
|
|
1986
|
+
const r = await apiCall('/api/my-products', { apiKey });
|
|
1987
|
+
if (Array.isArray(r))
|
|
1988
|
+
return { found: r.length, products: r };
|
|
1989
|
+
return r;
|
|
1990
|
+
}
|
|
1991
|
+
if (action === 'create') {
|
|
1992
|
+
const createFields = ['title', 'description', 'price', 'stock', 'category', 'specs', 'brand', 'model', 'source_url', 'source_price', 'external_title', 'weight_kg', 'ship_regions', 'handling_hours', 'estimated_days', 'fragile', 'return_days', 'return_condition', 'warranty_days', 'commission_rate', 'product_type', 'aliases', 'image_hashes'];
|
|
1993
|
+
const body = {};
|
|
1994
|
+
for (const k of createFields)
|
|
1995
|
+
if (args[k] !== undefined)
|
|
1996
|
+
body[k] = args[k];
|
|
1997
|
+
const created = await apiCall('/api/products', { method: 'POST', apiKey, body });
|
|
1998
|
+
if ('error' in created)
|
|
1999
|
+
return created;
|
|
2000
|
+
const newId = (created.product_id ?? created.id);
|
|
2001
|
+
const extraKeys = ['i18n_titles', 'i18n_descs', 'origin_claims', 'low_stock_threshold', 'auto_delist_on_zero'];
|
|
2002
|
+
if (newId && extraKeys.some(k => args[k] !== undefined)) {
|
|
2003
|
+
const eb = {};
|
|
2004
|
+
for (const k of extraKeys)
|
|
2005
|
+
if (args[k] !== undefined)
|
|
2006
|
+
eb[k] = args[k];
|
|
2007
|
+
const extra = await apiCall(`/api/products/${encodeURIComponent(newId)}`, { method: 'PUT', apiKey, body: eb });
|
|
2008
|
+
return { ...created, extra_fields_applied: !('error' in extra), extra_result: extra };
|
|
2009
|
+
}
|
|
2010
|
+
return created;
|
|
2011
|
+
}
|
|
2012
|
+
if (!pid)
|
|
2013
|
+
return { error: `product_id required for action=${action}` };
|
|
2014
|
+
if (action === 'update') {
|
|
2015
|
+
const updatable = ['title', 'description', 'price', 'stock', 'specs', 'brand', 'model', 'handling_hours', 'ship_regions', 'estimated_days', 'fragile', 'return_days', 'return_condition', 'warranty_days', 'low_stock_threshold', 'auto_delist_on_zero', 'i18n_titles', 'i18n_descs', 'origin_claims'];
|
|
2016
|
+
const body = {};
|
|
2017
|
+
for (const k of updatable)
|
|
2018
|
+
if (args[k] !== undefined)
|
|
2019
|
+
body[k] = args[k];
|
|
2020
|
+
return apiCall(`/api/products/${encodeURIComponent(pid)}`, { method: 'PUT', apiKey, body });
|
|
2021
|
+
}
|
|
2022
|
+
if (action === 'delist')
|
|
2023
|
+
return apiCall(`/api/products/${encodeURIComponent(pid)}/status`, { method: 'PATCH', apiKey, body: { status: 'warehouse' } });
|
|
2024
|
+
if (action === 'relist')
|
|
2025
|
+
return apiCall(`/api/products/${encodeURIComponent(pid)}/status`, { method: 'PATCH', apiKey, body: { status: 'active' } });
|
|
2026
|
+
if (action === 'trash')
|
|
2027
|
+
return apiCall(`/api/products/${encodeURIComponent(pid)}/status`, { method: 'PATCH', apiKey, body: { status: 'deleted' } });
|
|
2028
|
+
if (action === 'delete')
|
|
2029
|
+
return apiCall(`/api/products/${encodeURIComponent(pid)}`, { method: 'DELETE', apiKey });
|
|
2030
|
+
return { error: `unknown action: ${action}. Valid actions: create | mine | update | delist | relist | trash | delete` };
|
|
2031
|
+
}
|
|
1972
2032
|
if (action !== 'create') {
|
|
1973
2033
|
const auth0 = requireAuth(db, apiKey);
|
|
1974
2034
|
if ('error' in auth0)
|
|
@@ -2081,7 +2141,21 @@ async function handleListProduct(args) {
|
|
|
2081
2141
|
...(extraResult ? { extra_fields_applied: !('error' in extraResult), extra_result: extraResult } : {}),
|
|
2082
2142
|
};
|
|
2083
2143
|
}
|
|
2084
|
-
function handlePlaceOrder(args) {
|
|
2144
|
+
async function handlePlaceOrder(args) {
|
|
2145
|
+
// RFC-003 P2: network 模式转发到生产 POST /api/orders(前置,绕过本地 db)。
|
|
2146
|
+
// 生产端做完整鉴权/库存/session/spend-cap/结算。
|
|
2147
|
+
if (toolBackend('webaz_place_order') === 'network') {
|
|
2148
|
+
const body = { product_id: args.product_id, quantity: Number(args.quantity ?? 1) };
|
|
2149
|
+
if (args.session_token != null)
|
|
2150
|
+
body.session_token = args.session_token;
|
|
2151
|
+
if (args.expected_price != null)
|
|
2152
|
+
body.expected_price = args.expected_price;
|
|
2153
|
+
if (args.shipping_address != null)
|
|
2154
|
+
body.shipping_address = args.shipping_address;
|
|
2155
|
+
if (args.donation_pct != null)
|
|
2156
|
+
body.donation_pct = args.donation_pct;
|
|
2157
|
+
return apiCall('/api/orders', { method: 'POST', apiKey: args.api_key, body });
|
|
2158
|
+
}
|
|
2085
2159
|
const auth = requireAuth(db, args.api_key);
|
|
2086
2160
|
if ('error' in auth)
|
|
2087
2161
|
return auth;
|
|
@@ -2240,6 +2314,24 @@ function handlePlaceOrder(args) {
|
|
|
2240
2314
|
};
|
|
2241
2315
|
}
|
|
2242
2316
|
async function handleUpdateOrder(args) {
|
|
2317
|
+
// RFC-003 P2b: NETWORK 模式 — 全部状态机动作转发生产 /api/orders/:id/action(单一真相源;
|
|
2318
|
+
// sandbox 路径里 confirm 也是这么转发的,network 把整套履约状态机统一走 PWA 引擎)
|
|
2319
|
+
if (toolBackend('webaz_update_order') === 'network') {
|
|
2320
|
+
const orderId = args.order_id;
|
|
2321
|
+
const action = args.action;
|
|
2322
|
+
if (!orderId || !action)
|
|
2323
|
+
return { error: 'order_id and action required' };
|
|
2324
|
+
return apiCall(`/api/orders/${encodeURIComponent(orderId)}/action`, {
|
|
2325
|
+
method: 'POST',
|
|
2326
|
+
apiKey: args.api_key,
|
|
2327
|
+
body: {
|
|
2328
|
+
action,
|
|
2329
|
+
notes: args.notes ?? '',
|
|
2330
|
+
evidence_description: args.evidence_description ?? '',
|
|
2331
|
+
...(args.logistics_company_id ? { logistics_company_id: args.logistics_company_id } : {}),
|
|
2332
|
+
},
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2243
2335
|
const auth = requireAuth(db, args.api_key);
|
|
2244
2336
|
if ('error' in auth)
|
|
2245
2337
|
return auth;
|
|
@@ -2357,7 +2449,14 @@ async function handleUpdateOrder(args) {
|
|
|
2357
2449
|
history_record: result.historyId,
|
|
2358
2450
|
};
|
|
2359
2451
|
}
|
|
2360
|
-
function handleGetStatus(args) {
|
|
2452
|
+
async function handleGetStatus(args) {
|
|
2453
|
+
// RFC-003 P4: NETWORK 模式订单查询 → 生产 GET /api/orders/:id(权威网络订单详情 + 历史)
|
|
2454
|
+
if (toolBackend('webaz_get_status') === 'network') {
|
|
2455
|
+
const orderId = args.order_id;
|
|
2456
|
+
if (!orderId)
|
|
2457
|
+
return { error: 'order_id required' };
|
|
2458
|
+
return apiCall(`/api/orders/${encodeURIComponent(orderId)}`, { apiKey: args.api_key });
|
|
2459
|
+
}
|
|
2361
2460
|
const auth = requireAuth(db, args.api_key);
|
|
2362
2461
|
if ('error' in auth)
|
|
2363
2462
|
return auth;
|
|
@@ -3016,8 +3115,41 @@ function handleReferral(args) {
|
|
|
3016
3115
|
score_pending: score.pending,
|
|
3017
3116
|
waz_total_earned: score.settled_waz,
|
|
3018
3117
|
},
|
|
3118
|
+
rewards_status: (() => {
|
|
3119
|
+
// RFC-002 §3.5 — 4 states + pending escrow visibility (PR-4)
|
|
3120
|
+
const optIn = db.prepare("SELECT rewards_opted_in FROM users WHERE id = ?").get(userId)?.rewards_opted_in ?? 0;
|
|
3121
|
+
const lastAction = db.prepare("SELECT action FROM rewards_applications WHERE user_id = ? ORDER BY created_at DESC LIMIT 1").get(userId)?.action;
|
|
3122
|
+
let state;
|
|
3123
|
+
let note;
|
|
3124
|
+
if (optIn === 1) {
|
|
3125
|
+
state = 'opted_in';
|
|
3126
|
+
note = 'You have opted into rewards. Commissions credit to wallet immediately when orders settle.';
|
|
3127
|
+
}
|
|
3128
|
+
else if (lastAction === 'deactivate') {
|
|
3129
|
+
state = 'deactivated';
|
|
3130
|
+
note = 'You actively deactivated rewards. Future commissions redirect directly to charity_fund (no escrow). You can re-apply via PWA #me.';
|
|
3131
|
+
}
|
|
3132
|
+
else if (lastAction === 'auto_downgrade') {
|
|
3133
|
+
state = 'auto_downgraded';
|
|
3134
|
+
note = 'You were auto-downgraded (failed to re-confirm consent within grace window). Future commissions held in pending_commission_escrow (30d window) — re-confirm via PWA #me to recover them.';
|
|
3135
|
+
}
|
|
3136
|
+
else {
|
|
3137
|
+
state = 'never_activated';
|
|
3138
|
+
note = 'Rewards inactive — attributions recorded; commissions held in pending_commission_escrow (30d window per protocol_params.rewards_opt_in.escrow_days) until you activate via PWA #me.';
|
|
3139
|
+
}
|
|
3140
|
+
const pending = db.prepare("SELECT COUNT(*) AS n, COALESCE(SUM(amount),0) AS total FROM pending_commission_escrow WHERE recipient_user_id = ? AND status = 'pending'").get(userId);
|
|
3141
|
+
const expired = db.prepare("SELECT COUNT(*) AS n, COALESCE(SUM(amount),0) AS total FROM pending_commission_escrow WHERE recipient_user_id = ? AND status = 'expired'").get(userId);
|
|
3142
|
+
return {
|
|
3143
|
+
state,
|
|
3144
|
+
opted_in: optIn === 1,
|
|
3145
|
+
note,
|
|
3146
|
+
pending_escrow: { count: pending.n, total_amount: pending.total },
|
|
3147
|
+
expired_to_charity: { count: expired.n, total_amount: expired.total },
|
|
3148
|
+
spec: 'RFC-002 §3.5 — rewards opt-in / 共建身份申请制',
|
|
3149
|
+
};
|
|
3150
|
+
})(),
|
|
3019
3151
|
tip: canL1
|
|
3020
|
-
? 'Use webaz_share_link(product_id) to generate a product share link. Both 3-tier commission and PV tree will apply.'
|
|
3152
|
+
? 'Use webaz_share_link(product_id) to generate a product share link. Both 3-tier commission and PV tree will apply (only when rewards_opted_in=1).'
|
|
3021
3153
|
: 'Complete 1 purchase first, then your share link will earn 3-tier commission. Until then, your share builds PV tree only.',
|
|
3022
3154
|
};
|
|
3023
3155
|
}
|
|
@@ -3029,6 +3161,35 @@ function handleShareLink(args) {
|
|
|
3029
3161
|
const userId = user.id;
|
|
3030
3162
|
const productId = args.product_id;
|
|
3031
3163
|
const sideArg = args.side || 'auto';
|
|
3164
|
+
// RFC-002 §3.5 valuation-layer gate — share_link generation requires opt-in
|
|
3165
|
+
const optIn = db.prepare("SELECT rewards_opted_in FROM users WHERE id = ?").get(userId)?.rewards_opted_in ?? 0;
|
|
3166
|
+
if (optIn !== 1) {
|
|
3167
|
+
const getParam = (key, def) => {
|
|
3168
|
+
const r = db.prepare("SELECT value FROM protocol_params WHERE key = ?").get(key);
|
|
3169
|
+
return r ? Number(r.value) : def;
|
|
3170
|
+
};
|
|
3171
|
+
const minOrders = getParam('rewards_opt_in.min_completed_orders', 1);
|
|
3172
|
+
const requirePasskey = getParam('rewards_opt_in.require_passkey', 1);
|
|
3173
|
+
const totalCompleted = db.prepare("SELECT COUNT(*) as n FROM orders WHERE buyer_id = ? AND status = 'completed'").get(userId).n;
|
|
3174
|
+
const passkeyCount = db.prepare("SELECT COUNT(*) as n FROM webauthn_credentials WHERE user_id = ?").get(userId).n;
|
|
3175
|
+
const missing = [];
|
|
3176
|
+
if (totalCompleted < minOrders)
|
|
3177
|
+
missing.push(`completed_orders ${totalCompleted}/${minOrders}`);
|
|
3178
|
+
if (requirePasskey === 1 && passkeyCount === 0)
|
|
3179
|
+
missing.push('passkey_not_registered');
|
|
3180
|
+
if (missing.length === 0)
|
|
3181
|
+
missing.push('application_not_submitted');
|
|
3182
|
+
return {
|
|
3183
|
+
error: 'rewards_opt_in_required',
|
|
3184
|
+
message: 'Share-link generation is a valuation-layer action — requires builder-identity opt-in (RFC-002 §3.5)',
|
|
3185
|
+
missing_requirements: missing,
|
|
3186
|
+
next_steps: [
|
|
3187
|
+
'Open PWA #me → tap "申请共建身份 / Apply for builder identity"',
|
|
3188
|
+
'Read the 8-second disclosure (cannot skip)',
|
|
3189
|
+
'Submit application — pre-checks run server-side',
|
|
3190
|
+
],
|
|
3191
|
+
};
|
|
3192
|
+
}
|
|
3032
3193
|
const product = db.prepare("SELECT id, title, price, commission_rate FROM products WHERE id = ? AND status='active'").get(productId);
|
|
3033
3194
|
if (!product)
|
|
3034
3195
|
return { error: '商品不存在或已下架' };
|
|
@@ -3039,7 +3200,7 @@ function handleShareLink(args) {
|
|
|
3039
3200
|
else {
|
|
3040
3201
|
// auto = 与 PWA pickPreferredSide 对齐:尊重 placement_pref(team_count | pv_count)
|
|
3041
3202
|
// 老版只看 total_left_pv vs total_right_pv,team_count 用户被错算
|
|
3042
|
-
const u = db.prepare("SELECT placement_pref, total_left_pv, total_right_pv,
|
|
3203
|
+
const u = db.prepare("SELECT placement_pref, total_left_pv, total_right_pv, left_count, right_count FROM users WHERE id = ?")
|
|
3043
3204
|
.get(userId);
|
|
3044
3205
|
const pref = u?.placement_pref || 'team_count';
|
|
3045
3206
|
if (pref === 'pv_count') {
|
|
@@ -3052,22 +3213,10 @@ function handleShareLink(args) {
|
|
|
3052
3213
|
side = leftPv <= rightPv ? 'left' : 'right';
|
|
3053
3214
|
}
|
|
3054
3215
|
else {
|
|
3055
|
-
// team_count:
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
const row = db.prepare(`SELECT ${childField} FROM users WHERE id = ?`).get(current);
|
|
3060
|
-
const next = row?.[childField] || null;
|
|
3061
|
-
if (!next)
|
|
3062
|
-
break;
|
|
3063
|
-
count++;
|
|
3064
|
-
current = next;
|
|
3065
|
-
}
|
|
3066
|
-
return count;
|
|
3067
|
-
};
|
|
3068
|
-
const lCount = countLeg(userId, 'left_child_id');
|
|
3069
|
-
const rCount = countLeg(userId, 'right_child_id');
|
|
3070
|
-
side = lCount <= rCount ? 'left' : 'right';
|
|
3216
|
+
// team_count: 整棵子树人数(增量维护的 left_count/right_count,与 PWA pickPreferredSide 对齐)。
|
|
3217
|
+
// 2026-06-04 修:旧版沿单条脊链数(countLeg)名实不符 → 选边失真。分享链接的 side 会被注册时
|
|
3218
|
+
// 当 placement_side 显式采用,必须与 PWA joinPowerLeg 用同一指标,否则两路径不一致。
|
|
3219
|
+
side = (Number(u?.left_count ?? 0) <= Number(u?.right_count ?? 0)) ? 'left' : 'right';
|
|
3071
3220
|
}
|
|
3072
3221
|
}
|
|
3073
3222
|
const completed = db.prepare("SELECT COUNT(*) as n FROM orders WHERE buyer_id = ? AND status = 'completed'").get(userId).n;
|
|
@@ -3362,6 +3511,19 @@ function handleShareables(args) {
|
|
|
3362
3511
|
}
|
|
3363
3512
|
// ─── P3 RFQ / bid / chat / auto_bid(HTTP 转发到 PWA,复用所有校验+状态机)────
|
|
3364
3513
|
const PWA_API_BASE = process.env.WEBAZ_PWA_API_BASE || 'http://localhost:3000/api';
|
|
3514
|
+
// RFC-003 P1: 公开读端点按模式取数 —— network → apiCall(webaz.xyz + Bearer + 15s 超时);sandbox → 本地 PWA。
|
|
3515
|
+
// subpath 不含 /api 前缀(如 '/leaderboard?...'),内部按模式补齐。
|
|
3516
|
+
async function readEndpoint(tool, subpath) {
|
|
3517
|
+
if (toolBackend(tool) === 'network')
|
|
3518
|
+
return apiCall('/api' + subpath);
|
|
3519
|
+
try {
|
|
3520
|
+
const r = await fetch(PWA_API_BASE + subpath, { signal: AbortSignal.timeout(15_000) });
|
|
3521
|
+
return await r.json();
|
|
3522
|
+
}
|
|
3523
|
+
catch (e) {
|
|
3524
|
+
return { error: String(e.message) };
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3365
3527
|
async function pwaApi(method, path, apiKey, body) {
|
|
3366
3528
|
const opts = {
|
|
3367
3529
|
method,
|
|
@@ -3771,13 +3933,7 @@ async function handlePriceHistory(args) {
|
|
|
3771
3933
|
const pid = String(args.product_id || '');
|
|
3772
3934
|
if (!pid)
|
|
3773
3935
|
return { error: 'product_id required' };
|
|
3774
|
-
|
|
3775
|
-
const r = await fetch(PWA_API_BASE + '/products/' + encodeURIComponent(pid) + '/price-history');
|
|
3776
|
-
return await r.json();
|
|
3777
|
-
}
|
|
3778
|
-
catch (e) {
|
|
3779
|
-
return { error: String(e.message) };
|
|
3780
|
-
}
|
|
3936
|
+
return readEndpoint('webaz_price_history', '/products/' + encodeURIComponent(pid) + '/price-history');
|
|
3781
3937
|
}
|
|
3782
3938
|
async function handleCharity(args) {
|
|
3783
3939
|
const action = String(args.action || '');
|
|
@@ -3943,15 +4099,8 @@ async function handleLeaderboard(args) {
|
|
|
3943
4099
|
const VALID_KINDS = ['products', 'creators', 'buyers', 'sellers', 'value_products', 'agents', 'arbitrators', 'verifiers'];
|
|
3944
4100
|
if (!VALID_KINDS.includes(kind))
|
|
3945
4101
|
return { error: `kind 必须是 ${VALID_KINDS.join(' / ')}` };
|
|
3946
|
-
// 排行榜公开(不需 api_key
|
|
3947
|
-
|
|
3948
|
-
try {
|
|
3949
|
-
const r = await fetch(PWA_API_BASE + '/leaderboard?kind=' + kind + '&limit=' + limit);
|
|
3950
|
-
return await r.json();
|
|
3951
|
-
}
|
|
3952
|
-
catch (e) {
|
|
3953
|
-
return { error: `PWA API unreachable: ${e.message}` };
|
|
3954
|
-
}
|
|
4102
|
+
// 排行榜公开(不需 api_key)。RFC-003 P1:network 走 webaz.xyz,sandbox 走本地。
|
|
4103
|
+
return readEndpoint('webaz_leaderboard', '/leaderboard?kind=' + kind + '&limit=' + limit);
|
|
3955
4104
|
}
|
|
3956
4105
|
async function handleAuction(args) {
|
|
3957
4106
|
const apiKey = String(args.api_key || '');
|
|
@@ -4074,7 +4223,7 @@ export async function startMCPServer() {
|
|
|
4074
4223
|
{
|
|
4075
4224
|
uri: MANIFEST_URI,
|
|
4076
4225
|
name: 'WebAZ Protocol Manifest',
|
|
4077
|
-
description: '
|
|
4226
|
+
description: 'Full WebAZ machine-readable spec. Covers: state machine, economic model, roles, dispute system, Skill market, reputation, agent operating guide. Reading this is enough for an AI agent to participate in the protocol — no extra docs needed.',
|
|
4078
4227
|
mimeType: 'application/json',
|
|
4079
4228
|
},
|
|
4080
4229
|
],
|
|
@@ -4101,34 +4250,34 @@ export async function startMCPServer() {
|
|
|
4101
4250
|
const PROMPTS = [
|
|
4102
4251
|
{
|
|
4103
4252
|
name: 'webaz-place-order',
|
|
4104
|
-
description: '
|
|
4253
|
+
description: 'Guide buyer agent through discover → verify_price → lock → place_order (incl. precise match for pasted external links). Use this when the user hands you a product URL.',
|
|
4105
4254
|
arguments: [
|
|
4106
|
-
{ name: 'user_intent', description: '
|
|
4255
|
+
{ name: 'user_intent', description: 'User raw intent or pasted link text', required: true },
|
|
4107
4256
|
],
|
|
4108
4257
|
},
|
|
4109
4258
|
{
|
|
4110
4259
|
name: 'webaz-list-product',
|
|
4111
|
-
description: '
|
|
4260
|
+
description: 'Guide seller agent through product listing — covers SEO/agent-friendliness best practices (fill brand/model/specs/return_days/handling_hours and other Schema.org bonus fields).',
|
|
4112
4261
|
arguments: [
|
|
4113
|
-
{ name: 'product_summary', description: '
|
|
4262
|
+
{ name: 'product_summary', description: 'Seller-described product summary', required: true },
|
|
4114
4263
|
],
|
|
4115
4264
|
},
|
|
4116
4265
|
{
|
|
4117
4266
|
name: 'webaz-onboard',
|
|
4118
|
-
description: '
|
|
4267
|
+
description: 'Onboarding for a new agent first connecting to webaz — explains protocol nature / pre-launch state / MLM shape / registration path / user-authorization boundaries. Read webaz_info first, then run this prompt.',
|
|
4119
4268
|
arguments: [],
|
|
4120
4269
|
},
|
|
4121
4270
|
{
|
|
4122
4271
|
name: 'webaz-handle-dispute',
|
|
4123
|
-
description: '
|
|
4272
|
+
description: 'Guide handling when an order goes wrong — distinguishes three paths: negotiated refund / dispute arbitration / seller-initiated cancel. Reminds Iron-Rule (arbitrate requires PWA + Passkey).',
|
|
4124
4273
|
arguments: [
|
|
4125
|
-
{ name: 'order_id', description: '
|
|
4126
|
-
{ name: 'issue_summary', description: '
|
|
4274
|
+
{ name: 'order_id', description: 'The problematic order ID', required: true },
|
|
4275
|
+
{ name: 'issue_summary', description: 'Issue description (wrong item received / not received / quality problem, etc.)', required: true },
|
|
4127
4276
|
],
|
|
4128
4277
|
},
|
|
4129
4278
|
{
|
|
4130
4279
|
name: 'webaz-cross-border',
|
|
4131
|
-
description: '
|
|
4280
|
+
description: 'Onboarding for China cross-border sellers — domestic uses WebAZ native protocol / cross-border exposes UCP merchant endpoint to global agents. Explains dual-rail architecture + compliance boundaries.',
|
|
4132
4281
|
arguments: [],
|
|
4133
4282
|
},
|
|
4134
4283
|
];
|
|
@@ -4245,19 +4394,25 @@ export async function startMCPServer() {
|
|
|
4245
4394
|
result = await handleSearch(args);
|
|
4246
4395
|
break;
|
|
4247
4396
|
case 'webaz_verify_price':
|
|
4248
|
-
result = handleVerifyPrice(args);
|
|
4397
|
+
result = await handleVerifyPrice(args);
|
|
4249
4398
|
break;
|
|
4250
4399
|
case 'webaz_list_product':
|
|
4251
4400
|
result = await handleListProduct(args);
|
|
4252
4401
|
break;
|
|
4253
4402
|
case 'webaz_place_order':
|
|
4254
|
-
result = handlePlaceOrder(args);
|
|
4403
|
+
result = await handlePlaceOrder(args);
|
|
4255
4404
|
break;
|
|
4256
4405
|
case 'webaz_update_order':
|
|
4257
4406
|
result = await handleUpdateOrder(args);
|
|
4258
4407
|
break;
|
|
4259
4408
|
case 'webaz_get_status':
|
|
4260
|
-
result = handleGetStatus(args);
|
|
4409
|
+
result = await handleGetStatus(args);
|
|
4410
|
+
break;
|
|
4411
|
+
case 'webaz_feedback':
|
|
4412
|
+
result = await handleFeedback(args);
|
|
4413
|
+
break;
|
|
4414
|
+
case 'webaz_contribute':
|
|
4415
|
+
result = await handleContribute(args);
|
|
4261
4416
|
break;
|
|
4262
4417
|
case 'webaz_wallet':
|
|
4263
4418
|
result = await handleWallet(args);
|
|
@@ -4353,6 +4508,29 @@ export async function startMCPServer() {
|
|
|
4353
4508
|
result = { error: `执行出错:${err.message}` };
|
|
4354
4509
|
}
|
|
4355
4510
|
recordToolCall(name, args, result, Date.now() - t0);
|
|
4511
|
+
// RFC-004 现场证据:记本次调用的脱敏摘要(只 arg key 名,不含值)。webaz_feedback 自身不入 buffer。
|
|
4512
|
+
if (name !== 'webaz_feedback') {
|
|
4513
|
+
const isErr = !!result && typeof result === 'object' && 'error' in result;
|
|
4514
|
+
pushRecentCall({
|
|
4515
|
+
tool: name,
|
|
4516
|
+
arg_keys: Object.keys(args || {}).filter(k => k !== 'api_key'),
|
|
4517
|
+
outcome: isErr ? 'error' : 'ok',
|
|
4518
|
+
mode: toolBackend(name),
|
|
4519
|
+
ts: new Date().toISOString(),
|
|
4520
|
+
});
|
|
4521
|
+
}
|
|
4522
|
+
// RFC-003 P0: 给每个工具结果盖模式戳(诚实可见,防把 sandbox 当 live 网络)
|
|
4523
|
+
// P3: handler 可自行预设 _mode(如 register 在 network 模式返回引导,不是 sandbox 结果)→ 不覆盖。
|
|
4524
|
+
const backend = toolBackend(name);
|
|
4525
|
+
if (result && typeof result === 'object' && !Array.isArray(result)) {
|
|
4526
|
+
const r = result;
|
|
4527
|
+
if (!('_mode' in r))
|
|
4528
|
+
r._mode = backend;
|
|
4529
|
+
if (r._mode === 'sandbox' && !('_sandbox_note' in r)) {
|
|
4530
|
+
r._sandbox_note =
|
|
4531
|
+
'SANDBOX: 本地结果,非 webaz.xyz 全网真实状态 / local-only, NOT the live webaz.xyz network';
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4356
4534
|
return {
|
|
4357
4535
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
4358
4536
|
};
|
|
@@ -4360,6 +4538,7 @@ export async function startMCPServer() {
|
|
|
4360
4538
|
const transport = new StdioServerTransport();
|
|
4361
4539
|
await server.connect(transport);
|
|
4362
4540
|
console.error('✅ WebAZ MCP Server 已启动,等待 Agent 连接...');
|
|
4541
|
+
console.error(modeBanner());
|
|
4363
4542
|
}
|
|
4364
4543
|
// ─── 工具函数 ─────────────────────────────────────────────────
|
|
4365
4544
|
function addHours(date, hours) {
|