@wowok/agent-mcp 2.3.18 → 2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/customer/industry-risks.js +31 -31
- package/dist/customer/order-monitor.js +57 -57
- package/dist/customer/order-strategy.js +89 -89
- package/dist/customer/post-purchase.js +97 -97
- package/dist/customer/reminder-system.js +26 -26
- package/dist/customer/risk-assessment.js +46 -46
- package/dist/customer/types.d.ts +4 -4
- package/dist/customer/types.js +4 -4
- package/dist/customer/user-preferences.js +50 -50
- package/dist/experience/intent-distill.js +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -1624
- package/dist/knowledge/acquisition-flywheel.js +64 -64
- package/dist/knowledge/arbitration-trust.js +10 -10
- package/dist/knowledge/demand-matching.js +8 -8
- package/dist/knowledge/dynamic-pricing.js +18 -18
- package/dist/knowledge/flywheel-loop.js +11 -11
- package/dist/knowledge/glossary.js +22 -22
- package/dist/knowledge/guard-ledger.d.ts +1 -1
- package/dist/knowledge/guard-ledger.js +145 -104
- package/dist/knowledge/guard-lint.d.ts +77 -0
- package/dist/knowledge/guard-lint.js +670 -0
- package/dist/knowledge/guard-migration.d.ts +48 -0
- package/dist/knowledge/guard-migration.js +228 -0
- package/dist/knowledge/guard-puzzle.d.ts +109 -14
- package/dist/knowledge/guard-puzzle.js +627 -101
- package/dist/knowledge/guard-risk.d.ts +10 -1
- package/dist/knowledge/guard-risk.js +1634 -292
- package/dist/knowledge/guard-templates.d.ts +38 -0
- package/dist/knowledge/guard-templates.js +605 -0
- package/dist/knowledge/guard-translation.d.ts +14 -2
- package/dist/knowledge/guard-translation.js +825 -194
- package/dist/knowledge/index.d.ts +8 -4
- package/dist/knowledge/index.js +9 -5
- package/dist/knowledge/industry-evolution.js +29 -29
- package/dist/knowledge/industry-generalizer.js +52 -52
- package/dist/knowledge/industry-registry.js +20 -33
- package/dist/knowledge/intent-metrics.js +67 -67
- package/dist/knowledge/process-model.js +80 -80
- package/dist/knowledge/reputation-rules.js +9 -9
- package/dist/knowledge/reward-templates.js +51 -51
- package/dist/knowledge/safety-rules.js +3 -3
- package/dist/knowledge/tool-constraints.js +20 -4
- package/dist/knowledge/trust-metrics.js +26 -26
- package/dist/project/graph.d.ts +1 -0
- package/dist/project/graph.js +27 -1
- package/dist/project/index.d.ts +1 -0
- package/dist/project/index.js +39 -2
- package/dist/project/namespace.d.ts +11 -1
- package/dist/project/namespace.js +27 -2
- package/dist/project/query.d.ts +2 -0
- package/dist/project/query.js +56 -15
- package/dist/rules.d.ts +12 -0
- package/dist/rules.js +9 -0
- package/dist/schema/call/allocation.d.ts +10 -10
- package/dist/schema/call/base.js +19 -19
- package/dist/schema/call/bridge.d.ts +32 -32
- package/dist/schema/call/demand.d.ts +84 -84
- package/dist/schema/call/guard.d.ts +153 -0
- package/dist/schema/call/guard.js +50 -0
- package/dist/schema/call/machine.d.ts +38 -38
- package/dist/schema/call/permission.d.ts +78 -78
- package/dist/schema/call/repository.d.ts +22 -22
- package/dist/schema/call/semantic.js +229 -25
- package/dist/schema/call/service.d.ts +7 -7
- package/dist/schema/local/wip.d.ts +39 -19
- package/dist/schema/local/wip.js +5 -5
- package/dist/schema/messenger/index.d.ts +26 -26
- package/dist/schema/messenger/index.js +2 -2
- package/dist/schema/operations.d.ts +270 -192
- package/dist/schema/query/index.d.ts +184 -184
- package/dist/schema/query/index.js +15 -9
- package/dist/schema/trust/index.d.ts +4 -4
- package/dist/schema/utils/guard-parser.js +4 -4
- package/dist/schema/utils/guard-query-utils.d.ts +7 -0
- package/dist/schema/utils/guard-query-utils.js +14 -1
- package/dist/schema/utils/node-parser.js +14 -14
- package/dist/schemas/bridge_operation.output.json +15 -15
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/messenger_operation.output.json +18 -16
- package/dist/schemas/onchain_events.output.json +15 -15
- package/dist/schemas/onchain_operations.output.json +16 -16
- package/dist/schemas/onchain_operations.schema.json +11 -20
- package/dist/schemas/onchain_operations_allocation.schema.json +7 -10
- package/dist/schemas/onchain_operations_machine.schema.json +2 -5
- package/dist/schemas/onchain_operations_service.schema.json +2 -5
- package/dist/schemas/onchain_table_data.output.json +20 -26
- package/dist/schemas/wip_file.output.json +24 -1
- package/dist/tools/handlers/bridge.d.ts +1 -0
- package/dist/tools/handlers/bridge.js +1 -0
- package/dist/tools/handlers/config.d.ts +2 -0
- package/dist/tools/handlers/config.js +71 -0
- package/dist/tools/handlers/file-export.d.ts +3 -0
- package/dist/tools/handlers/file-export.js +90 -0
- package/dist/tools/handlers/local.d.ts +30 -0
- package/dist/tools/handlers/local.js +27 -0
- package/dist/tools/handlers/messenger.d.ts +16 -0
- package/dist/tools/handlers/messenger.js +187 -0
- package/dist/tools/handlers/onchain.d.ts +2 -0
- package/dist/tools/handlers/onchain.js +246 -0
- package/dist/tools/handlers/project.d.ts +2 -0
- package/dist/tools/handlers/project.js +53 -0
- package/dist/tools/handlers/query.d.ts +5 -0
- package/dist/tools/handlers/query.js +256 -0
- package/dist/tools/handlers/schema-query.d.ts +2 -0
- package/dist/tools/handlers/schema-query.js +92 -0
- package/dist/tools/handlers/trust.d.ts +2 -0
- package/dist/tools/handlers/trust.js +194 -0
- package/dist/tools/handlers/wip.d.ts +2 -0
- package/dist/tools/handlers/wip.js +44 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.js +479 -0
- package/dist/tools/rules-hook.d.ts +2 -0
- package/dist/tools/rules-hook.js +22 -0
- package/dist/tools/shared.d.ts +29 -0
- package/dist/tools/shared.js +130 -0
- package/dist/tools/types.d.ts +35 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/wrap.d.ts +6 -0
- package/dist/tools/wrap.js +55 -0
- package/package.json +19 -5
|
@@ -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: "
|
|
21
|
+
description: "Refund path exists (100%→Order Allocator)",
|
|
22
22
|
weight: 10,
|
|
23
23
|
passed: hasRefund,
|
|
24
|
-
advice: hasRefund ? undefined : "⚠️
|
|
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 : "⚠️
|
|
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: "
|
|
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 : `⚠️
|
|
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 = `⚠️
|
|
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 = "🔴
|
|
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: "
|
|
99
|
+
description: "100%→Order refund Allocator exists",
|
|
100
100
|
weight: 8,
|
|
101
101
|
passed: hasRefundAllocator,
|
|
102
|
-
advice: hasRefundAllocator ? undefined : "⚠️
|
|
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 : `⚠️
|
|
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: "
|
|
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 = `⚠️
|
|
149
|
+
reviewAdvice = `⚠️ Like rate is ${Math.round(likeRate * 100)}%; there is some controversy.`;
|
|
150
150
|
}
|
|
151
151
|
else {
|
|
152
152
|
reviewPassed = false;
|
|
153
|
-
reviewAdvice = `🔴
|
|
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: "
|
|
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:
|
|
175
|
+
description: `Composite trust score ≥50 (current ${trustScore})`,
|
|
176
176
|
weight: 4,
|
|
177
177
|
passed: trustPassed,
|
|
178
|
-
advice: trustPassed ? undefined : `🔴
|
|
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: "
|
|
185
|
+
description: "Merchant has a contactable Messenger channel",
|
|
186
186
|
weight: 5,
|
|
187
187
|
passed: hasContact && hasMessenger,
|
|
188
|
-
advice: (hasContact && hasMessenger) ? undefined : "🔴
|
|
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: "
|
|
225
|
+
description: "Order completion rate ≥85%",
|
|
226
226
|
weight: 4,
|
|
227
227
|
passed: completionPassed,
|
|
228
|
-
advice: completionPassed ? undefined : `🔴
|
|
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: "
|
|
234
|
+
description: "Dispute rate ≤10%",
|
|
235
235
|
weight: 4,
|
|
236
236
|
passed: disputeOk,
|
|
237
|
-
advice: disputeOk ? undefined : `⚠️
|
|
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: "
|
|
243
|
+
description: "Arbitration loss rate ≤30%",
|
|
244
244
|
weight: 3,
|
|
245
245
|
passed: arbLossOk,
|
|
246
|
-
advice: arbLossOk ? undefined : `🔴
|
|
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: "
|
|
252
|
+
description: "No behavior red_flags",
|
|
253
253
|
weight: 3,
|
|
254
254
|
passed: noRedFlags,
|
|
255
|
-
advice: noRedFlags ? undefined : `⚠️
|
|
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}
|
|
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("⚠️
|
|
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}
|
|
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(`ℹ️
|
|
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
|
}
|
package/dist/customer/types.d.ts
CHANGED
|
@@ -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>;
|
package/dist/customer/types.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export const CUSTOMER_INTELLIGENCE_VERSION = 1;
|
|
2
2
|
export const RISK_LEVELS = [
|
|
3
|
-
{ min: 85, level: "low", label: "
|
|
4
|
-
{ min: 70, level: "medium_low", label: "
|
|
5
|
-
{ min: 50, level: "medium_high", label: "
|
|
6
|
-
{ min: 0, level: "high", label: "
|
|
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(
|
|
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}
|
|
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(
|
|
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("
|
|
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
|
|
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(
|
|
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%
|
|
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}
|
|
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%
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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}
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
317
|
+
matches.push(`Merchant region ${service.merchant_region} matches preference`);
|
|
318
318
|
}
|
|
319
319
|
else if (service.merchant_region) {
|
|
320
|
-
mismatches.push(
|
|
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(
|
|
332
|
+
matches.push(`Merchant history ${service.merchant_order_history_count} orders ≥ required ${prefs.min_order_history} orders`);
|
|
333
333
|
}
|
|
334
334
|
else {
|
|
335
|
-
mismatches.push(
|
|
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(
|
|
340
|
+
matches.push(`Merchant type ${service.merchant_age} matches preference`);
|
|
341
341
|
}
|
|
342
342
|
else if (service.merchant_age !== "unknown") {
|
|
343
|
-
mismatches.push(
|
|
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("
|
|
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("
|
|
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(
|
|
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(
|
|
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("
|
|
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("
|
|
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(
|
|
398
|
+
matches.push(`Risk score ${service.risk_score} ≥ required ${prefs.min_trust_score}`);
|
|
399
399
|
}
|
|
400
400
|
else {
|
|
401
|
-
mismatches.push(
|
|
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("
|
|
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("
|
|
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 {
|