@wowok/agent-mcp 2.3.18 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/customer/industry-risks.js +31 -31
  2. package/dist/customer/order-monitor.js +57 -57
  3. package/dist/customer/order-strategy.js +89 -89
  4. package/dist/customer/post-purchase.js +97 -97
  5. package/dist/customer/reminder-system.js +26 -26
  6. package/dist/customer/risk-assessment.js +46 -46
  7. package/dist/customer/types.d.ts +4 -4
  8. package/dist/customer/types.js +4 -4
  9. package/dist/customer/user-preferences.js +50 -50
  10. package/dist/experience/intent-distill.js +6 -6
  11. package/dist/knowledge/acquisition-flywheel.js +64 -64
  12. package/dist/knowledge/arbitration-trust.js +10 -10
  13. package/dist/knowledge/demand-matching.js +8 -8
  14. package/dist/knowledge/dynamic-pricing.js +18 -18
  15. package/dist/knowledge/flywheel-loop.js +11 -11
  16. package/dist/knowledge/glossary.js +22 -22
  17. package/dist/knowledge/guard-ledger.d.ts +1 -1
  18. package/dist/knowledge/guard-ledger.js +131 -104
  19. package/dist/knowledge/guard-lint.d.ts +76 -0
  20. package/dist/knowledge/guard-lint.js +590 -0
  21. package/dist/knowledge/guard-puzzle.d.ts +109 -14
  22. package/dist/knowledge/guard-puzzle.js +627 -101
  23. package/dist/knowledge/guard-risk.d.ts +8 -1
  24. package/dist/knowledge/guard-risk.js +868 -296
  25. package/dist/knowledge/guard-templates.d.ts +37 -0
  26. package/dist/knowledge/guard-templates.js +329 -0
  27. package/dist/knowledge/guard-translation.d.ts +14 -2
  28. package/dist/knowledge/guard-translation.js +825 -194
  29. package/dist/knowledge/index.d.ts +8 -4
  30. package/dist/knowledge/index.js +9 -5
  31. package/dist/knowledge/industry-evolution.js +29 -29
  32. package/dist/knowledge/industry-generalizer.js +52 -52
  33. package/dist/knowledge/industry-registry.js +20 -33
  34. package/dist/knowledge/intent-metrics.js +67 -67
  35. package/dist/knowledge/process-model.js +80 -80
  36. package/dist/knowledge/reputation-rules.js +9 -9
  37. package/dist/knowledge/reward-templates.js +51 -51
  38. package/dist/knowledge/safety-rules.js +3 -3
  39. package/dist/knowledge/tool-constraints.js +20 -4
  40. package/dist/knowledge/trust-metrics.js +26 -26
  41. package/dist/schema/call/base.js +16 -16
  42. package/dist/schema/call/bridge.d.ts +32 -32
  43. package/dist/schema/call/demand.d.ts +84 -84
  44. package/dist/schema/call/guard.d.ts +153 -0
  45. package/dist/schema/call/guard.js +50 -0
  46. package/dist/schema/call/permission.d.ts +78 -78
  47. package/dist/schema/call/repository.d.ts +22 -22
  48. package/dist/schema/call/semantic.js +228 -24
  49. package/dist/schema/local/wip.d.ts +39 -19
  50. package/dist/schema/local/wip.js +5 -5
  51. package/dist/schema/messenger/index.d.ts +26 -26
  52. package/dist/schema/messenger/index.js +2 -2
  53. package/dist/schema/operations.d.ts +222 -144
  54. package/dist/schema/query/index.d.ts +38 -38
  55. package/dist/schema/trust/index.d.ts +4 -4
  56. package/dist/schema/utils/guard-parser.js +4 -4
  57. package/dist/schema/utils/node-parser.js +14 -14
  58. package/dist/schemas/bridge_operation.output.json +14 -14
  59. package/dist/schemas/index.json +1 -1
  60. package/dist/schemas/messenger_operation.output.json +17 -15
  61. package/dist/schemas/onchain_events.output.json +14 -14
  62. package/dist/schemas/onchain_operations.output.json +14 -14
  63. package/dist/schemas/onchain_table_data.output.json +14 -14
  64. package/dist/schemas/wip_file.output.json +24 -1
  65. package/package.json +2 -2
@@ -5,7 +5,7 @@ export function riskLevelFromScore(score) {
5
5
  }
6
6
  export function riskLevelLabel(level) {
7
7
  const entry = RISK_LEVELS.find((l) => l.level === level);
8
- return entry ? `${entry.color} ${entry.label}` : "🔴 高风险";
8
+ return entry ? `${entry.color} ${entry.label}` : "🔴 High risk";
9
9
  }
10
10
  export function riskLevelEmoji(level) {
11
11
  const entry = RISK_LEVELS.find((l) => l.level === level);
@@ -18,47 +18,47 @@ function assessWorkflowRisk(puzzle) {
18
18
  checks.push({
19
19
  id: "wf_refund_path",
20
20
  dimension: "workflow",
21
- description: "存在退款路径(100%→Order Allocator",
21
+ description: "Refund path exists (100%→Order Allocator)",
22
22
  weight: 10,
23
23
  passed: hasRefund,
24
- advice: hasRefund ? undefined : "⚠️ 无退款路径:若交付失败,资金可能无法回收。建议下单前通过 Messenger 与商家协商退款条款并写入 WTS",
24
+ advice: hasRefund ? undefined : "⚠️ No refund path: if delivery fails, funds may not be recoverable. Recommend negotiating refund terms with the merchant via Messenger and writing them into the WTS before ordering.",
25
25
  });
26
26
  const hasArb = wf?.has_arbitration_path ?? false;
27
27
  checks.push({
28
28
  id: "wf_arbitration_path",
29
29
  dimension: "workflow",
30
- description: "存在仲裁路径",
30
+ description: "Arbitration path exists",
31
31
  weight: 10,
32
32
  passed: hasArb,
33
- advice: hasArb ? undefined : "⚠️ 无仲裁路径:纠纷无法升级到第三方仲裁。建议要求商家绑定 Arbitration 服务后再下单。",
33
+ advice: hasArb ? undefined : "⚠️ No arbitration path: disputes cannot be escalated to third-party arbitration. Recommend requiring the merchant to bind an Arbitration service before ordering.",
34
34
  });
35
35
  const userOps = wf?.user_operable_forwards ?? 0;
36
36
  checks.push({
37
37
  id: "wf_user_operable",
38
38
  dimension: "workflow",
39
- description: "至少 1 条用户可操作 Forward",
39
+ description: "At least 1 user-operable Forward",
40
40
  weight: 8,
41
41
  passed: userOps > 0,
42
- advice: userOps > 0 ? undefined : "🔴 流程中无任何用户可操作步骤:订单进度完全依赖商家,你将处于被动地位。",
42
+ advice: userOps > 0 ? undefined : "🔴 No user-operable steps in the workflow: order progress depends entirely on the merchant, leaving you in a passive position.",
43
43
  });
44
44
  const deadEnds = wf?.dead_end_nodes ?? [];
45
45
  const noDeadEnds = deadEnds.length === 0;
46
46
  checks.push({
47
47
  id: "wf_no_dead_ends",
48
48
  dimension: "workflow",
49
- description: "无潜在死端节点",
49
+ description: "No potential dead-end nodes",
50
50
  weight: 4,
51
51
  passed: noDeadEnds,
52
- advice: noDeadEnds ? undefined : `⚠️ 检测到 ${deadEnds.length} 个潜在死端节点:${deadEnds.join(", ")}。这些节点的所有出口都依赖商家操作。`,
52
+ advice: noDeadEnds ? undefined : `⚠️ Detected ${deadEnds.length} potential dead-end node(s): ${deadEnds.join(", ")}. All exits of these nodes depend on merchant action.`,
53
53
  });
54
54
  const machineUsable = wf ? (wf.machine_published && !wf.machine_paused) : false;
55
55
  checks.push({
56
56
  id: "wf_machine_usable",
57
57
  dimension: "workflow",
58
- description: "Machine 已发布且未暂停",
58
+ description: "Machine is published and not paused",
59
59
  weight: 3,
60
60
  passed: machineUsable,
61
- advice: machineUsable ? undefined : "⚠️ Machine 未发布或已暂停:流程可能尚未生效或被商家主动暂停。",
61
+ advice: machineUsable ? undefined : "⚠️ Machine is not published or is paused: the workflow may not be in effect or has been actively paused by the merchant.",
62
62
  });
63
63
  const score = checks.reduce((sum, c) => sum + (c.passed ? c.weight : 0), 0);
64
64
  return { name: "workflow", score, max_score: RISK_DIMENSION_MAX.workflow, checks };
@@ -74,11 +74,11 @@ function assessFundRisk(puzzle) {
74
74
  }
75
75
  else if (fund.compensation_ratio > 0) {
76
76
  compScore = Math.round(fund.compensation_ratio * 10);
77
- compAdvice = `⚠️ 赔偿金仅覆盖订单金额的 ${Math.round(fund.compensation_ratio * 100)}%,不足以全额赔付。`;
77
+ compAdvice = `⚠️ Compensation fund covers only ${Math.round(fund.compensation_ratio * 100)}% of the order amount; insufficient for a full payout.`;
78
78
  }
79
79
  else {
80
80
  compScore = 0;
81
- compAdvice = "🔴 无赔偿金:商家未设置 compensation_fund,订单失败时无自动赔付来源。";
81
+ compAdvice = "🔴 No compensation fund: the merchant has not set up a compensation_fund; no automatic payout source if the order fails.";
82
82
  }
83
83
  }
84
84
  else {
@@ -87,7 +87,7 @@ function assessFundRisk(puzzle) {
87
87
  checks.push({
88
88
  id: "fund_compensation",
89
89
  dimension: "fund",
90
- description: "赔偿金充足度(覆盖订单金额)",
90
+ description: "Compensation fund adequacy (covers the order amount)",
91
91
  weight: 10,
92
92
  passed: compScore >= 7,
93
93
  advice: compAdvice,
@@ -96,28 +96,28 @@ function assessFundRisk(puzzle) {
96
96
  checks.push({
97
97
  id: "fund_refund_allocator",
98
98
  dimension: "fund",
99
- description: "存在 100%→Order 退款 Allocator",
99
+ description: "100%→Order refund Allocator exists",
100
100
  weight: 8,
101
101
  passed: hasRefundAllocator,
102
- advice: hasRefundAllocator ? undefined : "⚠️ 未检测到 100%→Order Allocator:退款需要商家手动操作或通过仲裁裁定。",
102
+ advice: hasRefundAllocator ? undefined : "⚠️ No 100%→Order Allocator detected: refunds require manual merchant action or arbitration ruling.",
103
103
  });
104
104
  const priceOk = fund ? fund.price_anomaly === "none" : true;
105
105
  checks.push({
106
106
  id: "fund_price_normal",
107
107
  dimension: "fund",
108
- description: "价格无异常(与赔偿金和市场价比对)",
108
+ description: "No price anomaly (compared with compensation fund and market price)",
109
109
  weight: 4,
110
110
  passed: priceOk,
111
- advice: priceOk ? undefined : `⚠️ 价格异常(${fund?.price_anomaly}):可能存在欺诈定价或异常低价诱惑。`,
111
+ advice: priceOk ? undefined : `⚠️ Price anomaly (${fund?.price_anomaly}): possible fraudulent pricing or abnormally-low-price lure.`,
112
112
  });
113
113
  const lockSafe = fund?.lock_duration_safe ?? true;
114
114
  checks.push({
115
115
  id: "fund_lock_safe",
116
116
  dimension: "fund",
117
- description: "赔偿金锁定期合理(≥7天或无锁定)",
117
+ description: "Compensation fund lock period is reasonable (≥7 days or no lock)",
118
118
  weight: 3,
119
119
  passed: lockSafe,
120
- advice: lockSafe ? undefined : "⚠️ 赔偿金锁定期过短:商家可能随时撤回资金。",
120
+ advice: lockSafe ? undefined : "⚠️ Compensation fund lock period is too short: the merchant may withdraw funds at any time.",
121
121
  });
122
122
  const naiveScore = checks.reduce((sum, c) => sum + (c.passed ? c.weight : 0), 0);
123
123
  const score = fund && !fund.compensation_covers_order && fund.compensation_ratio > 0
@@ -132,10 +132,10 @@ function assessTrustRisk(puzzle) {
132
132
  checks.push({
133
133
  id: "trust_arb_independent",
134
134
  dimension: "trust",
135
- description: "仲裁方与商家无利益关联",
135
+ description: "Arbitrator has no conflict of interest with the merchant",
136
136
  weight: 6,
137
137
  passed: arbIndependent,
138
- advice: arbIndependent ? undefined : "🔴 仲裁方与商家为同一地址:仲裁公正性无法保证。",
138
+ advice: arbIndependent ? undefined : "🔴 Arbitrator and merchant are the same address: arbitration fairness cannot be guaranteed.",
139
139
  });
140
140
  let reviewPassed = false;
141
141
  let reviewAdvice;
@@ -146,11 +146,11 @@ function assessTrustRisk(puzzle) {
146
146
  }
147
147
  else if (likeRate >= 0.6) {
148
148
  reviewPassed = true;
149
- reviewAdvice = `⚠️ 好评率 ${Math.round(likeRate * 100)}%,存在一定争议。`;
149
+ reviewAdvice = `⚠️ Like rate is ${Math.round(likeRate * 100)}%; there is some controversy.`;
150
150
  }
151
151
  else {
152
152
  reviewPassed = false;
153
- reviewAdvice = `🔴 好评率仅 ${Math.round(likeRate * 100)}%(${trust.review_likes}/${trust.review_total}),差评较多。`;
153
+ reviewAdvice = `🔴 Like rate is only ${Math.round(likeRate * 100)}% (${trust.review_likes}/${trust.review_total}); many negative reviews.`;
154
154
  }
155
155
  }
156
156
  else if (trust) {
@@ -162,7 +162,7 @@ function assessTrustRisk(puzzle) {
162
162
  checks.push({
163
163
  id: "trust_review_reputation",
164
164
  dimension: "trust",
165
- description: "评价声誉良好(好评率 ≥60%)",
165
+ description: "Good review reputation (like rate ≥60%)",
166
166
  weight: 5,
167
167
  passed: reviewPassed,
168
168
  advice: reviewAdvice,
@@ -172,20 +172,20 @@ function assessTrustRisk(puzzle) {
172
172
  checks.push({
173
173
  id: "trust_score",
174
174
  dimension: "trust",
175
- description: `综合信任分 ≥50(当前 ${trustScore})`,
175
+ description: `Composite trust score ≥50 (current ${trustScore})`,
176
176
  weight: 4,
177
177
  passed: trustPassed,
178
- advice: trustPassed ? undefined : `🔴 综合信任分仅 ${trustScore}/100,建议寻找更高信任度的商家。`,
178
+ advice: trustPassed ? undefined : `🔴 Composite trust score is only ${trustScore}/100; recommend finding a more trustworthy merchant.`,
179
179
  });
180
180
  const hasContact = trust?.has_contact ?? false;
181
181
  const hasMessenger = trust?.has_messenger ?? false;
182
182
  checks.push({
183
183
  id: "trust_contact",
184
184
  dimension: "trust",
185
- description: "商家有可联系的 Messenger 通道",
185
+ description: "Merchant has a contactable Messenger channel",
186
186
  weight: 5,
187
187
  passed: hasContact && hasMessenger,
188
- advice: (hasContact && hasMessenger) ? undefined : "🔴 商家无可联系通道(um 为空):无法进行 pre-order 协商或售后沟通。",
188
+ advice: (hasContact && hasMessenger) ? undefined : "🔴 Merchant has no contactable channel (um is empty): no way to conduct pre-order negotiation or post-sale communication.",
189
189
  });
190
190
  const score = checks.reduce((sum, c) => sum + (c.passed ? c.weight : 0), 0);
191
191
  return { name: "trust", score, max_score: RISK_DIMENSION_MAX.trust, checks };
@@ -204,7 +204,7 @@ function assessBehaviorRisk(puzzle) {
204
204
  }
205
205
  else {
206
206
  trendPassed = false;
207
- trendAdvice = "🔴 商家近期争议率上升:履约质量可能在恶化。";
207
+ trendAdvice = "🔴 Merchant's recent dispute rate is rising: fulfillment quality may be deteriorating.";
208
208
  }
209
209
  }
210
210
  else {
@@ -213,7 +213,7 @@ function assessBehaviorRisk(puzzle) {
213
213
  checks.push({
214
214
  id: "behavior_trend",
215
215
  dimension: "behavior",
216
- description: "近期履约趋势稳定或改善",
216
+ description: "Recent fulfillment trend is stable or improving",
217
217
  weight: 6,
218
218
  passed: trendPassed,
219
219
  advice: trendAdvice,
@@ -222,37 +222,37 @@ function assessBehaviorRisk(puzzle) {
222
222
  checks.push({
223
223
  id: "behavior_completion_rate",
224
224
  dimension: "behavior",
225
- description: "订单完成率 ≥85%",
225
+ description: "Order completion rate ≥85%",
226
226
  weight: 4,
227
227
  passed: completionPassed,
228
- advice: completionPassed ? undefined : `🔴 完成率仅 ${Math.round((beh?.completed_rate ?? 0) * 100)}%:高于平均的订单以失败告终。`,
228
+ advice: completionPassed ? undefined : `🔴 Completion rate is only ${Math.round((beh?.completed_rate ?? 0) * 100)}%: a higher-than-average share of orders end in failure.`,
229
229
  });
230
230
  const disputeOk = beh ? beh.dispute_rate <= 0.1 : true;
231
231
  checks.push({
232
232
  id: "behavior_low_dispute",
233
233
  dimension: "behavior",
234
- description: "争议率 ≤10%",
234
+ description: "Dispute rate ≤10%",
235
235
  weight: 4,
236
236
  passed: disputeOk,
237
- advice: disputeOk ? undefined : `⚠️ 争议率 ${Math.round((beh?.dispute_rate ?? 0) * 100)}%:高于行业平均水平。`,
237
+ advice: disputeOk ? undefined : `⚠️ Dispute rate is ${Math.round((beh?.dispute_rate ?? 0) * 100)}%: above the industry average.`,
238
238
  });
239
239
  const arbLossOk = beh ? beh.arb_loss_rate <= 0.3 : true;
240
240
  checks.push({
241
241
  id: "behavior_arb_loss",
242
242
  dimension: "behavior",
243
- description: "仲裁败诉率 ≤30%",
243
+ description: "Arbitration loss rate ≤30%",
244
244
  weight: 3,
245
245
  passed: arbLossOk,
246
- advice: arbLossOk ? undefined : `🔴 仲裁败诉率 ${Math.round((beh?.arb_loss_rate ?? 0) * 100)}%:商家多次在仲裁中败诉,存在违规倾向。`,
246
+ advice: arbLossOk ? undefined : `🔴 Arbitration loss rate is ${Math.round((beh?.arb_loss_rate ?? 0) * 100)}%: the merchant has lost multiple arbitration cases, indicating a tendency to violate rules.`,
247
247
  });
248
248
  const noRedFlags = beh ? beh.red_flags.length === 0 : true;
249
249
  checks.push({
250
250
  id: "behavior_no_red_flags",
251
251
  dimension: "behavior",
252
- description: "无行为 red_flags",
252
+ description: "No behavior red_flags",
253
253
  weight: 3,
254
254
  passed: noRedFlags,
255
- advice: noRedFlags ? undefined : `⚠️ 检测到行为警示信号:${beh?.red_flags.join(", ")}`,
255
+ advice: noRedFlags ? undefined : `⚠️ Detected behavioral warning signals: ${beh?.red_flags.join(", ")}`,
256
256
  });
257
257
  const score = checks.reduce((sum, c) => sum + (c.passed ? c.weight : 0), 0);
258
258
  return { name: "behavior", score, max_score: RISK_DIMENSION_MAX.behavior, checks };
@@ -297,18 +297,18 @@ function generateAdvice(puzzle, total, level, dimensions) {
297
297
  const advice = [];
298
298
  const emoji = riskLevelEmoji(level);
299
299
  const levelEntry = RISK_LEVELS.find((l) => l.level === level);
300
- advice.push(`${emoji} 综合风险评分:${total}/100(${levelEntry?.label ?? "未知"})`);
300
+ advice.push(`${emoji} Composite risk score: ${total}/100 (${levelEntry?.label ?? "unknown"})`);
301
301
  if (level === "high") {
302
- advice.push("🚫 建议放弃此订单:风险水平过高,资金安全无法保证。");
302
+ advice.push("🚫 Recommend abandoning this order: the risk level is too high; fund safety cannot be guaranteed.");
303
303
  }
304
304
  else if (level === "medium_high") {
305
- advice.push("⚠️ 建议谨慎下单:务必通过 Messenger 协商补充条款,并要求生成 WTS 凭证。");
305
+ advice.push("⚠️ Recommend ordering with caution: be sure to negotiate supplementary terms via Messenger and request a WTS evidence file.");
306
306
  }
307
307
  else if (level === "medium_low") {
308
- advice.push("✅ 可以下单:建议持续关注订单进度,保留沟通记录。");
308
+ advice.push("✅ You may order: recommend continuously monitoring order progress and keeping communication records.");
309
309
  }
310
310
  else {
311
- advice.push("✅ 安全订单:可放心下单,仍建议启用订单监控提醒。");
311
+ advice.push("✅ Safe order: you can order with confidence; still recommend enabling order monitoring reminders.");
312
312
  }
313
313
  const sortedDims = [...dimensions].sort((a, b) => (a.score / a.max_score) - (b.score / b.max_score));
314
314
  for (const dim of sortedDims) {
@@ -316,7 +316,7 @@ function generateAdvice(puzzle, total, level, dimensions) {
316
316
  if (ratio < 0.5) {
317
317
  const failedChecks = dim.checks.filter((c) => !c.passed);
318
318
  if (failedChecks.length > 0) {
319
- advice.push(`📊 ${dim.name} 维度 ${dim.score}/${dim.max_score}:${failedChecks.length} 项未通过。`);
319
+ advice.push(`📊 ${dim.name} dimension ${dim.score}/${dim.max_score}: ${failedChecks.length} check(s) failed.`);
320
320
  const critical = failedChecks.find((c) => c.advice?.startsWith("🔴"));
321
321
  if (critical?.advice)
322
322
  advice.push(critical.advice);
@@ -324,7 +324,7 @@ function generateAdvice(puzzle, total, level, dimensions) {
324
324
  }
325
325
  }
326
326
  if (puzzle.completeness < 0.8) {
327
- advice.push(`ℹ️ 信息完整度仅 ${Math.round(puzzle.completeness * 100)}%,缺失:${puzzle.gaps.join(", ") || ""}。建议补充数据后再决策。`);
327
+ advice.push(`ℹ️ Information completeness is only ${Math.round(puzzle.completeness * 100)}%; missing: ${puzzle.gaps.join(", ") || "none"}. Recommend supplementing data before making a decision.`);
328
328
  }
329
329
  return advice;
330
330
  }
@@ -172,22 +172,22 @@ export declare const CUSTOMER_INTELLIGENCE_VERSION = 1;
172
172
  export declare const RISK_LEVELS: readonly [{
173
173
  readonly min: 85;
174
174
  readonly level: "low";
175
- readonly label: "低风险";
175
+ readonly label: "Low risk";
176
176
  readonly color: "🟢";
177
177
  }, {
178
178
  readonly min: 70;
179
179
  readonly level: "medium_low";
180
- readonly label: "中低风险";
180
+ readonly label: "Medium-low risk";
181
181
  readonly color: "🟡";
182
182
  }, {
183
183
  readonly min: 50;
184
184
  readonly level: "medium_high";
185
- readonly label: "中高风险";
185
+ readonly label: "Medium-high risk";
186
186
  readonly color: "🟠";
187
187
  }, {
188
188
  readonly min: 0;
189
189
  readonly level: "high";
190
- readonly label: "高风险";
190
+ readonly label: "High risk";
191
191
  readonly color: "🔴";
192
192
  }];
193
193
  export declare const RISK_DIMENSION_MAX: Record<RiskDimensionName, number>;
@@ -1,9 +1,9 @@
1
1
  export const CUSTOMER_INTELLIGENCE_VERSION = 1;
2
2
  export const RISK_LEVELS = [
3
- { min: 85, level: "low", label: "低风险", color: "🟢" },
4
- { min: 70, level: "medium_low", label: "中低风险", color: "🟡" },
5
- { min: 50, level: "medium_high", label: "中高风险", color: "🟠" },
6
- { min: 0, level: "high", label: "高风险", color: "🔴" },
3
+ { min: 85, level: "low", label: "Low risk", color: "🟢" },
4
+ { min: 70, level: "medium_low", label: "Medium-low risk", color: "🟡" },
5
+ { min: 50, level: "medium_high", label: "Medium-high risk", color: "🟠" },
6
+ { min: 0, level: "high", label: "High risk", color: "🔴" },
7
7
  ];
8
8
  export const RISK_DIMENSION_MAX = {
9
9
  workflow: 35,
@@ -96,7 +96,7 @@ export function inferPreferences(history, basePrefs) {
96
96
  const confidence = {};
97
97
  const signals = [];
98
98
  if (history.length < 3) {
99
- signals.push(`history=${history.length} < 3,沿用默认偏好`);
99
+ signals.push(`history=${history.length} < 3, keeping default preferences`);
100
100
  return { preferences: prefs, confidence, signals };
101
101
  }
102
102
  const lowPricePicks = history.filter((h) => h.avg_market_price > 0n && h.price < (h.avg_market_price * 90n) / 100n);
@@ -105,28 +105,28 @@ export function inferPreferences(history, basePrefs) {
105
105
  prefs.value_orientation = "budget";
106
106
  confidence.price_sensitivity = 0.8;
107
107
  confidence.value_orientation = 0.7;
108
- signals.push(`连续 ${lowPricePicks.length} 次选择低于均价 10%+ Service → price_sensitivity=high`);
108
+ signals.push(`Consecutive ${lowPricePicks.length} picks of Service priced 10%+ below average → price_sensitivity=high`);
109
109
  }
110
110
  else if (lowPricePicks.length >= 1) {
111
111
  prefs.price_sensitivity = "medium";
112
112
  confidence.price_sensitivity = 0.5;
113
- signals.push(`${lowPricePicks.length} 次低价选择 → price_sensitivity=medium`);
113
+ signals.push(`${lowPricePicks.length} low-price picks → price_sensitivity=medium`);
114
114
  }
115
115
  const discountUsers = history.filter((h) => h.used_discount);
116
116
  if (discountUsers.length >= 2) {
117
117
  prefs.discount_sensitivity = 0.8;
118
118
  confidence.discount_sensitivity = 0.85;
119
- signals.push(`使用折扣 ${discountUsers.length} → discount_sensitivity=0.8`);
119
+ signals.push(`Used discount ${discountUsers.length} times → discount_sensitivity=0.8`);
120
120
  }
121
121
  if (history.some((h) => h.used_referral)) {
122
122
  prefs.referral_participation = true;
123
123
  confidence.referral_participation = 1.0;
124
- signals.push("使用过推荐码 → referral_participation=true");
124
+ signals.push("Has used a referral code → referral_participation=true");
125
125
  }
126
126
  if (discountUsers.length >= 2 || history.some((h) => h.used_referral)) {
127
127
  prefs.reward_seeking = true;
128
128
  confidence.reward_seeking = 0.75;
129
- signals.push("Reward 行为检测到 → reward_seeking=true");
129
+ signals.push("Reward behavior detected → reward_seeking=true");
130
130
  }
131
131
  const bargainSignals = discountUsers.length + (history.some((h) => h.used_referral) ? 1 : 0);
132
132
  if (bargainSignals >= 3) {
@@ -151,24 +151,24 @@ export function inferPreferences(history, basePrefs) {
151
151
  if (preferredIndustries.length > 0) {
152
152
  prefs.preferred_industries = preferredIndustries;
153
153
  confidence.preferred_industries = Math.min(1, (industryCounts.get(preferredIndustries[0]) ?? 0) / 5);
154
- signals.push(`偏好行业:${preferredIndustries.join(", ")}`);
154
+ signals.push(`Preferred industries: ${preferredIndustries.join(", ")}`);
155
155
  }
156
156
  const arbPicks = history.filter((h) => h.has_arbitration);
157
157
  if (arbPicks.length >= 3 && arbPicks.length === history.length) {
158
158
  prefs.require_arbitration = true;
159
159
  confidence.require_arbitration = 0.85;
160
- signals.push("100% 历史订单选择有仲裁的 Service → require_arbitration=true (confirmed)");
160
+ signals.push("100% of historical orders picked Services with arbitration → require_arbitration=true (confirmed)");
161
161
  }
162
162
  else if (arbPicks.length < history.length / 2) {
163
163
  prefs.require_arbitration = false;
164
164
  confidence.require_arbitration = 0.5;
165
- signals.push(`${arbPicks.length}/${history.length} 订单有仲裁 → require_arbitration=false`);
165
+ signals.push(`${arbPicks.length}/${history.length} orders had arbitration → require_arbitration=false`);
166
166
  }
167
167
  const compPicks = history.filter((h) => h.has_compensation);
168
168
  if (compPicks.length >= 3 && compPicks.length === history.length) {
169
169
  prefs.require_compensation_fund = true;
170
170
  confidence.require_compensation_fund = 0.85;
171
- signals.push("100% 历史订单有赔偿金 → require_compensation_fund=true (confirmed)");
171
+ signals.push("100% of historical orders had compensation fund → require_compensation_fund=true (confirmed)");
172
172
  }
173
173
  else if (compPicks.length < history.length / 2) {
174
174
  prefs.require_compensation_fund = false;
@@ -184,13 +184,13 @@ export function inferPreferences(history, basePrefs) {
184
184
  prefs.min_trust_score = 70;
185
185
  confidence.risk_appetite = 0.8;
186
186
  confidence.min_trust_score = 0.7;
187
- signals.push(`历史订单最低风险分 ${minRisk} ≥ 70 → risk_appetite=conservative`);
187
+ signals.push(`Lowest risk score in history ${minRisk} ≥ 70 → risk_appetite=conservative`);
188
188
  }
189
189
  else if (minRisk < 50) {
190
190
  prefs.risk_appetite = "aggressive";
191
191
  prefs.min_trust_score = Math.max(0, minRisk - 10);
192
192
  confidence.risk_appetite = 0.7;
193
- signals.push(`历史订单最低风险分 ${minRisk} < 50 → risk_appetite=aggressive`);
193
+ signals.push(`Lowest risk score in history ${minRisk} < 50 → risk_appetite=aggressive`);
194
194
  }
195
195
  }
196
196
  const messengerUsers = history.filter((h) => h.used_messenger);
@@ -199,12 +199,12 @@ export function inferPreferences(history, basePrefs) {
199
199
  if (avgMsgs >= 10) {
200
200
  prefs.communication_style = "formal";
201
201
  confidence.communication_style = 0.6;
202
- signals.push(`平均 ${avgMsgs.toFixed(1)} Messenger 消息 → communication_style=formal`);
202
+ signals.push(`Average ${avgMsgs.toFixed(1)} Messenger messages → communication_style=formal`);
203
203
  }
204
204
  else if (avgMsgs <= 3) {
205
205
  prefs.communication_style = "casual";
206
206
  confidence.communication_style = 0.5;
207
- signals.push(`平均 ${avgMsgs.toFixed(1)} Messenger 消息 → communication_style=casual`);
207
+ signals.push(`Average ${avgMsgs.toFixed(1)} Messenger messages → communication_style=casual`);
208
208
  }
209
209
  prefs.transparency_demand = Math.min(1, avgMsgs / 20);
210
210
  confidence.transparency_demand = 0.6;
@@ -215,7 +215,7 @@ export function inferPreferences(history, basePrefs) {
215
215
  prefs.after_sales_expectation = "full";
216
216
  confidence.transparency_demand = Math.max(confidence.transparency_demand ?? 0, 0.7);
217
217
  confidence.after_sales_expectation = 0.7;
218
- signals.push(`${disputedCount} 次争议 → transparency_demand 提升,after_sales=full`);
218
+ signals.push(`${disputedCount} disputes → transparency_demand increased, after_sales=full`);
219
219
  }
220
220
  const merchantCounts = new Map();
221
221
  for (const h of history) {
@@ -230,7 +230,7 @@ export function inferPreferences(history, basePrefs) {
230
230
  .map(([m]) => m);
231
231
  if (prefs.preferred_merchants.length > 0) {
232
232
  confidence.preferred_merchants = 0.8;
233
- signals.push(`惠顾 ${prefs.preferred_merchants.length} 个商家 ≥2 次`);
233
+ signals.push(`Patronized ${prefs.preferred_merchants.length} merchants ≥2 times`);
234
234
  }
235
235
  return { preferences: prefs, confidence, signals };
236
236
  }
@@ -244,14 +244,14 @@ export function matchServiceToPreferences(service, prefs) {
244
244
  if (prefs.budget_range) {
245
245
  if (service.price >= prefs.budget_range.min && service.price <= prefs.budget_range.max) {
246
246
  score += 20;
247
- matches.push("价格在预算区间内");
247
+ matches.push("Price within budget range");
248
248
  }
249
249
  else if (service.price < prefs.budget_range.min) {
250
250
  score += 15;
251
- matches.push("价格低于预算下限");
251
+ matches.push("Price below budget minimum");
252
252
  }
253
253
  else {
254
- mismatches.push("价格超出预算上限");
254
+ mismatches.push("Price exceeds budget maximum");
255
255
  }
256
256
  }
257
257
  else if (service.avg_market_price && service.avg_market_price > 0n) {
@@ -259,30 +259,30 @@ export function matchServiceToPreferences(service, prefs) {
259
259
  if (prefs.price_sensitivity === "high") {
260
260
  if (ratio <= 0.9) {
261
261
  score += 25;
262
- matches.push(`价格低于均价 ${(1 - ratio) * 100 | 0}%(高敏感度用户加分)`);
262
+ matches.push(`Price is ${(1 - ratio) * 100 | 0}% below average (bonus for high-sensitivity user)`);
263
263
  }
264
264
  else if (ratio <= 1.1) {
265
265
  score += 15;
266
- matches.push("价格与均价持平");
266
+ matches.push("Price on par with average");
267
267
  }
268
268
  else {
269
- mismatches.push(`价格高于均价 ${((ratio - 1) * 100 | 0)}%(高敏感度用户)`);
269
+ mismatches.push(`Price is ${((ratio - 1) * 100 | 0)}% above average (high-sensitivity user)`);
270
270
  }
271
271
  }
272
272
  else if (prefs.price_sensitivity === "low") {
273
273
  score += 20;
274
- matches.push("低价格敏感度");
274
+ matches.push("Low price sensitivity");
275
275
  }
276
276
  else {
277
277
  if (ratio <= 1.0) {
278
278
  score += 20;
279
- matches.push("价格不高于均价");
279
+ matches.push("Price not above average");
280
280
  }
281
281
  else if (ratio <= 1.2) {
282
282
  score += 12;
283
283
  }
284
284
  else {
285
- mismatches.push("价格显著高于均价");
285
+ mismatches.push("Price significantly above average");
286
286
  }
287
287
  }
288
288
  }
@@ -294,17 +294,17 @@ export function matchServiceToPreferences(service, prefs) {
294
294
  if (cycle > 0) {
295
295
  if (cycle <= prefs.max_acceptable_cycle) {
296
296
  score += 10;
297
- matches.push(`交付周期 ${cycle}期望 ${prefs.max_acceptable_cycle}天`);
297
+ matches.push(`Delivery cycle ${cycle} days expected ${prefs.max_acceptable_cycle} days`);
298
298
  if (prefs.delivery_speed_priority === "urgent" && cycle <= Math.max(1, prefs.max_acceptable_cycle / 3)) {
299
299
  score += 5;
300
- matches.push("紧急交付需求得到满足");
300
+ matches.push("Urgent delivery need satisfied");
301
301
  }
302
302
  else if (prefs.delivery_speed_priority === "urgent") {
303
- warnings.push("紧急交付需求但周期较长");
303
+ warnings.push("Urgent delivery need but cycle is long");
304
304
  }
305
305
  }
306
306
  else {
307
- mismatches.push(`交付周期 ${cycle} > 期望 ${prefs.max_acceptable_cycle}天`);
307
+ mismatches.push(`Delivery cycle ${cycle} days > expected ${prefs.max_acceptable_cycle} days`);
308
308
  }
309
309
  }
310
310
  else {
@@ -314,10 +314,10 @@ export function matchServiceToPreferences(service, prefs) {
314
314
  if (prefs.preferred_region) {
315
315
  if (service.merchant_region && service.merchant_region === prefs.preferred_region) {
316
316
  score += 10;
317
- matches.push(`商家地域 ${service.merchant_region} 与偏好一致`);
317
+ matches.push(`Merchant region ${service.merchant_region} matches preference`);
318
318
  }
319
319
  else if (service.merchant_region) {
320
- mismatches.push(`商家地域 ${service.merchant_region} 与偏好 ${prefs.preferred_region} 不符`);
320
+ mismatches.push(`Merchant region ${service.merchant_region} does not match preference ${prefs.preferred_region}`);
321
321
  }
322
322
  else {
323
323
  score += 5;
@@ -329,18 +329,18 @@ export function matchServiceToPreferences(service, prefs) {
329
329
  maxScore += 10;
330
330
  if (service.merchant_order_history_count >= prefs.min_order_history) {
331
331
  score += 7;
332
- matches.push(`商家历史 ${service.merchant_order_history_count} 要求 ${prefs.min_order_history} 单`);
332
+ matches.push(`Merchant history ${service.merchant_order_history_count} ordersrequired ${prefs.min_order_history} orders`);
333
333
  }
334
334
  else {
335
- mismatches.push(`商家历史 ${service.merchant_order_history_count} < 要求 ${prefs.min_order_history} 单`);
335
+ mismatches.push(`Merchant history ${service.merchant_order_history_count} orders < required ${prefs.min_order_history} orders`);
336
336
  }
337
337
  if (prefs.merchant_preference !== "neutral") {
338
338
  if (service.merchant_age === prefs.merchant_preference) {
339
339
  score += 3;
340
- matches.push(`商家类型 ${service.merchant_age} 符合偏好`);
340
+ matches.push(`Merchant type ${service.merchant_age} matches preference`);
341
341
  }
342
342
  else if (service.merchant_age !== "unknown") {
343
- mismatches.push(`商家类型 ${service.merchant_age} ≠ 偏好 ${prefs.merchant_preference}`);
343
+ mismatches.push(`Merchant type ${service.merchant_age} ≠ preference ${prefs.merchant_preference}`);
344
344
  }
345
345
  }
346
346
  else {
@@ -350,14 +350,14 @@ export function matchServiceToPreferences(service, prefs) {
350
350
  let bargainScore = 0;
351
351
  if (service.has_reward_activity) {
352
352
  bargainScore += 8;
353
- matches.push(" Reward 活动");
353
+ matches.push("Has Reward activity");
354
354
  }
355
355
  if (service.has_discount) {
356
356
  bargainScore += 7;
357
- matches.push("有折扣");
357
+ matches.push("Has discount");
358
358
  }
359
359
  if (prefs.bargain_hunting >= 0.7 && bargainScore === 0) {
360
- mismatches.push("用户高 bargain_hunting 但无 Reward/折扣");
360
+ mismatches.push("User has high bargain_hunting but no Reward/discount");
361
361
  }
362
362
  else if (prefs.bargain_hunting < 0.3) {
363
363
  if (bargainScore === 0)
@@ -372,22 +372,22 @@ export function matchServiceToPreferences(service, prefs) {
372
372
  maxScore += 10;
373
373
  if (service.after_sales_support_level === prefs.after_sales_expectation) {
374
374
  score += 5;
375
- matches.push(`售后支持 ${service.after_sales_support_level} 符合期望`);
375
+ matches.push(`After-sales support ${service.after_sales_support_level} matches expectation`);
376
376
  }
377
377
  else if ((prefs.after_sales_expectation === "full" && service.after_sales_support_level === "basic") ||
378
378
  (prefs.after_sales_expectation === "full" && service.after_sales_support_level === "minimal") ||
379
379
  (prefs.after_sales_expectation === "basic" && service.after_sales_support_level === "minimal")) {
380
- mismatches.push(`售后支持 ${service.after_sales_support_level} < 期望 ${prefs.after_sales_expectation}`);
380
+ mismatches.push(`After-sales support ${service.after_sales_support_level} < expectation ${prefs.after_sales_expectation}`);
381
381
  }
382
382
  else {
383
383
  score += 3;
384
384
  }
385
385
  if (prefs.transparency_demand >= 0.7 && service.requires_messenger) {
386
386
  score += 5;
387
- matches.push("商家支持 Messenger 沟通(高透明度需求)");
387
+ matches.push("Merchant supports Messenger communication (high transparency demand)");
388
388
  }
389
389
  else if (prefs.transparency_demand >= 0.7 && !service.requires_messenger) {
390
- mismatches.push("高透明度需求但商家无 Messenger");
390
+ mismatches.push("High transparency demand but merchant has no Messenger");
391
391
  }
392
392
  else {
393
393
  score += 3;
@@ -395,19 +395,19 @@ export function matchServiceToPreferences(service, prefs) {
395
395
  maxScore += 15;
396
396
  if (service.risk_score >= prefs.min_trust_score) {
397
397
  score += 8;
398
- matches.push(`风险分 ${service.risk_score} ≥ 要求 ${prefs.min_trust_score}`);
398
+ matches.push(`Risk score ${service.risk_score} ≥ required ${prefs.min_trust_score}`);
399
399
  }
400
400
  else {
401
- mismatches.push(`风险分 ${service.risk_score} < 要求 ${prefs.min_trust_score}`);
401
+ mismatches.push(`Risk score ${service.risk_score} < required ${prefs.min_trust_score}`);
402
402
  }
403
403
  if (prefs.require_arbitration) {
404
404
  if (service.has_arbitration) {
405
405
  score += 4;
406
- matches.push("配置了仲裁");
406
+ matches.push("Arbitration configured");
407
407
  }
408
408
  else {
409
- mismatches.push("用户要求仲裁但 Service 未配置");
410
- warnings.push("⚠️ 无仲裁:用户偏好要求必备仲裁");
409
+ mismatches.push("User requires arbitration but Service is not configured");
410
+ warnings.push("⚠️ No arbitration: user preference requires arbitration as mandatory");
411
411
  }
412
412
  }
413
413
  else {
@@ -416,11 +416,11 @@ export function matchServiceToPreferences(service, prefs) {
416
416
  if (prefs.require_compensation_fund) {
417
417
  if (service.has_compensation_fund) {
418
418
  score += 3;
419
- matches.push("有赔偿金");
419
+ matches.push("Has compensation fund");
420
420
  }
421
421
  else {
422
- mismatches.push("用户要求赔偿金但 Service ");
423
- warnings.push("⚠️ 无赔偿金:用户偏好要求必备");
422
+ mismatches.push("User requires compensation fund but Service has none");
423
+ warnings.push("⚠️ No compensation fund: user preference requires it as mandatory");
424
424
  }
425
425
  }
426
426
  else {