@wowok/agent-mcp 2.6.1 → 2.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/customer/customer-advice.d.ts +31 -0
- package/dist/customer/customer-advice.js +129 -0
- package/dist/customer/index.d.ts +2 -0
- package/dist/customer/index.js +2 -0
- package/dist/customer/info-puzzle.d.ts +9 -2
- package/dist/customer/info-puzzle.js +34 -7
- package/dist/customer/order-monitor.d.ts +2 -0
- package/dist/customer/order-monitor.js +3 -2
- package/dist/customer/post-purchase.d.ts +2 -0
- package/dist/customer/post-purchase.js +6 -5
- package/dist/customer/preorder-compare.d.ts +24 -0
- package/dist/customer/preorder-compare.js +34 -0
- package/dist/customer/reminder-system.d.ts +2 -0
- package/dist/customer/reminder-system.js +2 -1
- package/dist/customer/risk-assessment.js +30 -7
- package/dist/customer/types.d.ts +7 -0
- package/dist/examples/arbitration-dispute-create.json +41 -0
- package/dist/examples/arbitration-vote-weighted.json +35 -0
- package/dist/examples/arbitration-voting-guard-add.json +38 -0
- package/dist/examples/demand-present-service.json +33 -0
- package/dist/examples/gen-passport-verify-guard.json +48 -0
- package/dist/examples/guard-template-balance-check.json +59 -0
- package/dist/examples/guard-template-time-lock.json +60 -0
- package/dist/examples/insurance-guard-claim-timelock.json +75 -0
- package/dist/examples/insurance-guard-withdraw-allocation.json +96 -0
- package/dist/examples/insurance-machine-create-publish.json +75 -0
- package/dist/examples/insurance-service-allocators-publish.json +56 -0
- package/dist/examples/machine-multisig-threshold.json +86 -0
- package/dist/examples/machine-template-7node-rental.json +119 -0
- package/dist/examples/payment-scenario-bound.json +45 -0
- package/dist/examples/rental-ziroom-machine-create.json +149 -0
- package/dist/examples/rental-ziroom-permission-create.json +42 -0
- package/dist/examples/rental-ziroom-service-create.json +89 -0
- package/dist/examples/retail-adv-guard-customer-win-create.json +80 -0
- package/dist/examples/retail-adv-guard-messenger-proof-create.json +65 -0
- package/dist/examples/retail-adv-guard-reward-timeout-create.json +92 -0
- package/dist/examples/retail-adv-reward-guard-add.json +51 -0
- package/dist/examples/retail-myshop-allocation-activate.json +55 -0
- package/dist/examples/retail-myshop-arbitration-create.json +40 -0
- package/dist/examples/retail-myshop-contact-create.json +43 -0
- package/dist/examples/retail-myshop-order-create.json +56 -0
- package/dist/examples/retail-myshop-progress-operate.json +38 -0
- package/dist/examples/retail-myshop-reward-create.json +35 -0
- package/dist/examples/retail-myshop-service-create.json +88 -0
- package/dist/examples/service-discount-issue.json +46 -0
- package/dist/examples/threebody-guard-create.json +56 -0
- package/dist/examples/threebody-machine-create.json +72 -0
- package/dist/examples/threebody-permission-create.json +38 -0
- package/dist/examples/threebody-service-allocators.json +49 -0
- package/dist/examples/travel-guard-time-lock.json +69 -0
- package/dist/examples/travel-guard-weather-oracle.json +70 -0
- package/dist/examples/travel-machine-create.json +136 -0
- package/dist/examples/travel-repository-create.json +47 -0
- package/dist/examples/travel-service-create.json +102 -0
- package/dist/examples/travel-treasury-create.json +34 -0
- package/dist/examples/treasury-deposit.json +37 -0
- package/dist/examples/treasury-withdraw.json +38 -0
- package/dist/extensions/business-modules.d.ts +49 -0
- package/dist/extensions/business-modules.js +287 -0
- package/dist/extensions/capability-manifest.js +216 -29
- package/dist/extensions/constraint-registry.js +21 -19
- package/dist/extensions/metric-registry.js +14 -14
- package/dist/extensions/mode-evaluator.js +16 -16
- package/dist/extensions/modes.js +141 -49
- package/dist/extensions/registry.d.ts +16 -9
- package/dist/extensions/registry.js +132 -44
- package/dist/extensions/types.d.ts +2 -0
- package/dist/index.js +50 -0
- package/dist/knowledge/deployment-scanner.js +1 -1
- package/dist/knowledge/fund-layer.d.ts +138 -0
- package/dist/knowledge/fund-layer.js +969 -0
- package/dist/knowledge/guard-render.d.ts +57 -0
- package/dist/knowledge/guard-render.js +700 -0
- package/dist/knowledge/guard-submission-prompt.d.ts +31 -0
- package/dist/knowledge/guard-submission-prompt.js +171 -0
- package/dist/knowledge/guard-templates.d.ts +10 -0
- package/dist/knowledge/guard-templates.js +50 -0
- package/dist/knowledge/index.d.ts +2 -2
- package/dist/knowledge/index.js +2 -2
- package/dist/knowledge/machine-ledger.js +1 -1
- package/dist/knowledge/machine-render.d.ts +41 -0
- package/dist/knowledge/machine-render.js +565 -0
- package/dist/knowledge/machine-risk.js +4 -1
- package/dist/knowledge/machine-templates.js +4 -4
- package/dist/knowledge/progress-context.js +1 -1
- package/dist/knowledge/progress-ledger.js +3 -3
- package/dist/knowledge/progress-templates.js +1 -1
- package/dist/knowledge/progress-translation.js +1 -1
- package/dist/knowledge/reward-confirm.js +2 -2
- package/dist/knowledge/reward-puzzle.js +1 -1
- package/dist/knowledge/reward-risk.js +9 -9
- package/dist/knowledge/reward-templates.js +2 -2
- package/dist/knowledge/safety-rules.d.ts +83 -1
- package/dist/knowledge/safety-rules.js +166 -2
- package/dist/knowledge/scenario-modes.d.ts +1 -1
- package/dist/knowledge/scenario-modes.js +13 -11
- package/dist/knowledge/service-confirm.d.ts +1 -1
- package/dist/knowledge/service-confirm.js +3 -3
- package/dist/knowledge/service-context.js +1 -1
- package/dist/knowledge/service-ledger.js +1 -1
- package/dist/knowledge/service-risk.d.ts +1 -1
- package/dist/knowledge/service-risk.js +3 -3
- package/dist/knowledge/service-templates.js +2 -2
- package/dist/knowledge/service-translation.d.ts +1 -1
- package/dist/knowledge/service-translation.js +7 -7
- package/dist/knowledge/template-registry.d.ts +48 -0
- package/dist/knowledge/template-registry.js +341 -0
- package/dist/knowledge/tool-constraints.js +6 -6
- package/dist/knowledge/tools-reference.js +11 -8
- package/dist/participation/merchant-interest.d.ts +32 -0
- package/dist/participation/merchant-interest.js +100 -0
- package/dist/participation/radar-core.d.ts +104 -0
- package/dist/participation/radar-core.js +269 -0
- package/dist/project/context-assembly.js +8 -0
- package/dist/project/deployment-bridge.js +6 -5
- package/dist/project/deployment-doc.js +5 -5
- package/dist/project/edit-planner.d.ts +123 -0
- package/dist/project/edit-planner.js +1342 -0
- package/dist/project/evaluation.d.ts +36 -0
- package/dist/project/evaluation.js +734 -68
- package/dist/project/game-theory.d.ts +43 -0
- package/dist/project/game-theory.js +177 -0
- package/dist/project/graph-builder.js +7 -1
- package/dist/project/handlers.d.ts +137 -2
- package/dist/project/handlers.js +423 -51
- package/dist/project/intent-analyzer.d.ts +71 -0
- package/dist/project/intent-analyzer.js +149 -0
- package/dist/project/machine-nodes.d.ts +2 -0
- package/dist/project/machine-nodes.js +36 -0
- package/dist/project/merchant-guide.d.ts +165 -0
- package/dist/project/merchant-guide.js +264 -0
- package/dist/project/mode-actions.d.ts +199 -0
- package/dist/project/mode-actions.js +309 -0
- package/dist/project/participation-radar.d.ts +18 -0
- package/dist/project/participation-radar.js +428 -0
- package/dist/project/pipeline-actions.d.ts +101 -0
- package/dist/project/pipeline-actions.js +109 -0
- package/dist/project/semantic-graph.d.ts +95 -0
- package/dist/project/semantic-graph.js +245 -0
- package/dist/project/stage-gate.js +4 -4
- package/dist/schema/call/allocation.d.ts +11 -11
- package/dist/schema/call/allocation.js +13 -3
- package/dist/schema/call/arbitration.d.ts +21 -21
- package/dist/schema/call/arbitration.js +30 -9
- package/dist/schema/call/base.d.ts +2 -2
- package/dist/schema/call/base.js +1 -1
- package/dist/schema/call/bridge.d.ts +127 -127
- package/dist/schema/call/bridge.js +12 -12
- package/dist/schema/call/contact.d.ts +3 -3
- package/dist/schema/call/contact.js +2 -2
- package/dist/schema/call/demand.d.ts +3 -3
- package/dist/schema/call/demand.js +2 -2
- package/dist/schema/call/guard.d.ts +11 -11
- package/dist/schema/call/guard.js +2 -2
- package/dist/schema/call/machine.d.ts +2072 -679
- package/dist/schema/call/machine.js +51 -5
- package/dist/schema/call/order.d.ts +7 -7
- package/dist/schema/call/order.js +3 -6
- package/dist/schema/call/payment.d.ts +3 -3
- package/dist/schema/call/permission.d.ts +3 -3
- package/dist/schema/call/permission.js +2 -2
- package/dist/schema/call/personal.d.ts +337 -3
- package/dist/schema/call/personal.js +10 -0
- package/dist/schema/call/progress.d.ts +177 -9
- package/dist/schema/call/progress.js +7 -3
- package/dist/schema/call/proof.d.ts +6 -6
- package/dist/schema/call/repository.d.ts +3 -3
- package/dist/schema/call/repository.js +2 -2
- package/dist/schema/call/reward.d.ts +57 -57
- package/dist/schema/call/reward.js +3 -3
- package/dist/schema/call/semantic.js +48 -2
- package/dist/schema/call/service.d.ts +285 -113
- package/dist/schema/call/service.js +92 -28
- package/dist/schema/call/treasury.d.ts +57 -57
- package/dist/schema/call/treasury.js +3 -3
- package/dist/schema/common/index.d.ts +2 -0
- package/dist/schema/common/index.js +46 -10
- package/dist/schema/local/index.js +5 -1
- package/dist/schema/messenger/index.js +4 -1
- package/dist/schema/operations.d.ts +1318 -317
- package/dist/schema/operations.js +76 -7
- package/dist/schema/project/index.d.ts +5662 -164
- package/dist/schema/project/index.js +1136 -5
- package/dist/schema/query/index.d.ts +580 -19
- package/dist/schema/query/index.js +88 -36
- package/dist/schema/schema-query/index.d.ts +59 -3
- package/dist/schema/schema-query/index.js +45 -6
- package/dist/schema/trust/index.d.ts +1012 -6
- package/dist/schema/trust/index.js +212 -11
- package/dist/schema/utils/node-parser.js +13 -0
- package/dist/schema/utils/object-type-utils.d.ts +12 -0
- package/dist/schema/utils/object-type-utils.js +35 -0
- package/dist/schema/utils/permission-machine-check.d.ts +49 -0
- package/dist/schema/utils/permission-machine-check.js +121 -0
- package/dist/schema/utils/skills-recommendation.d.ts +2 -0
- package/dist/schema/utils/skills-recommendation.js +77 -0
- package/dist/schema-query/index.d.ts +17 -1
- package/dist/schema-query/index.js +359 -3
- package/dist/schemas/account_operation.schema.json +1 -1
- package/dist/schemas/bridge_operation.schema.json +14 -7
- package/dist/schemas/guard2file.schema.json +2 -0
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/machineNode2file.schema.json +2 -0
- package/dist/schemas/messenger_operation.schema.json +1 -1
- package/dist/schemas/onchain_events.output.json +1 -1
- package/dist/schemas/onchain_operations.output.json +2820 -0
- package/dist/schemas/onchain_operations.schema.json +255 -65
- package/dist/schemas/onchain_operations_allocation.schema.json +7 -6
- package/dist/schemas/onchain_operations_arbitration.schema.json +14 -10
- package/dist/schemas/onchain_operations_contact.schema.json +4 -3
- package/dist/schemas/onchain_operations_demand.schema.json +4 -3
- package/dist/schemas/onchain_operations_gen_passport.schema.json +4 -2
- package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -0
- package/dist/schemas/onchain_operations_guard.schema.json +579 -1
- package/dist/schemas/onchain_operations_machine.schema.json +5 -4
- package/dist/schemas/onchain_operations_order.schema.json +7 -6
- package/dist/schemas/onchain_operations_payment.schema.json +2 -1
- package/dist/schemas/onchain_operations_permission.schema.json +3 -2
- package/dist/schemas/onchain_operations_personal.schema.json +37 -0
- package/dist/schemas/onchain_operations_progress.schema.json +91 -4
- package/dist/schemas/onchain_operations_proof.schema.json +2 -1
- package/dist/schemas/onchain_operations_repository.schema.json +4 -3
- package/dist/schemas/onchain_operations_reward.schema.json +7 -6
- package/dist/schemas/onchain_operations_service.schema.json +80 -19
- package/dist/schemas/onchain_operations_treasury.schema.json +5 -4
- package/dist/schemas/onchain_table_data.output.json +1 -1
- package/dist/schemas/onchain_table_data.schema.json +10 -9
- package/dist/schemas/project_operation.output.json +3318 -57
- package/dist/schemas/project_operation.schema.json +728 -4
- package/dist/schemas/query_toolkit.output.json +16 -16
- package/dist/schemas/query_toolkit.schema.json +40 -3
- package/dist/schemas/schema_query.output.json +65 -2
- package/dist/schemas/schema_query.schema.json +31 -5
- package/dist/schemas/trust_score.output.json +392 -1
- package/dist/schemas/trust_score.schema.json +275 -1
- package/dist/schemas/wowok_buildin_info.output.json +81 -8
- package/dist/schemas/wowok_buildin_info.schema.json +46 -2
- package/dist/tools/handlers/onchain.js +636 -6
- package/dist/tools/handlers/project.js +71 -2
- package/dist/tools/handlers/query.js +117 -2
- package/dist/tools/handlers/schema-query.js +65 -1
- package/dist/tools/handlers/trust.js +192 -6
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +229 -15
- package/dist/tools/wrap.js +194 -15
- package/package.json +2 -2
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type InfoPuzzle, type RiskScore, type UserPreferences, type Industry, type StrategyRecommendation, type PreferenceMatchResult, type ServiceForMatching, type IndustryRiskResult, type Reminder, type ReminderContext } from "./index.js";
|
|
2
|
+
export interface PreorderAdviceInput {
|
|
3
|
+
puzzle: InfoPuzzle;
|
|
4
|
+
risk?: RiskScore;
|
|
5
|
+
preferences?: UserPreferences;
|
|
6
|
+
industry?: Industry;
|
|
7
|
+
matching_overrides?: Partial<ServiceForMatching>;
|
|
8
|
+
reminder_overrides?: Partial<ReminderContext>;
|
|
9
|
+
max_strategies?: number;
|
|
10
|
+
max_reminders?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ConfidenceScore {
|
|
13
|
+
score: number;
|
|
14
|
+
base: number;
|
|
15
|
+
user_adjustment: number;
|
|
16
|
+
preference_nudge: number;
|
|
17
|
+
explanation: string;
|
|
18
|
+
}
|
|
19
|
+
export interface PreorderAdvice {
|
|
20
|
+
service_id: string;
|
|
21
|
+
risk: RiskScore;
|
|
22
|
+
industry?: Industry;
|
|
23
|
+
strategies: StrategyRecommendation[];
|
|
24
|
+
preference_match?: PreferenceMatchResult;
|
|
25
|
+
industry_risks?: IndustryRiskResult;
|
|
26
|
+
reminders: Reminder[];
|
|
27
|
+
blocking_reminders: Reminder[];
|
|
28
|
+
confidence: ConfidenceScore;
|
|
29
|
+
summary: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function assemblePreorderAdvice(input: PreorderAdviceInput): PreorderAdvice;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { assessRisk, detectScenarios, recommendStrategy, matchServiceToPreferences, assessIndustryRisks, inferIndustry, generateReminders, getBlockingReminders, sortAndCapReminders, } from "./index.js";
|
|
2
|
+
import { registryDisplayHint } from "../knowledge/fund-layer.js";
|
|
3
|
+
export function assemblePreorderAdvice(input) {
|
|
4
|
+
const { puzzle } = input;
|
|
5
|
+
const risk = input.risk ?? assessRisk(puzzle);
|
|
6
|
+
const industry = input.industry ?? inferIndustry(puzzle);
|
|
7
|
+
const scenarios = detectScenarios(puzzle);
|
|
8
|
+
const strategies = scenarios
|
|
9
|
+
.slice(0, input.max_strategies ?? 3)
|
|
10
|
+
.map(s => recommendStrategy(s, { puzzle, prefs: input.preferences }));
|
|
11
|
+
let preferenceMatch;
|
|
12
|
+
if (input.preferences) {
|
|
13
|
+
const service = toMatchingService(puzzle, risk, input.matching_overrides);
|
|
14
|
+
preferenceMatch = matchServiceToPreferences(service, input.preferences);
|
|
15
|
+
}
|
|
16
|
+
let industryRisks;
|
|
17
|
+
if (industry) {
|
|
18
|
+
industryRisks = assessIndustryRisks(puzzle, industry);
|
|
19
|
+
}
|
|
20
|
+
const reminderCtx = buildReminderContext(puzzle, risk, input.reminder_overrides);
|
|
21
|
+
const reminders = sortAndCapReminders(generateReminders(reminderCtx))
|
|
22
|
+
.slice(0, input.max_reminders ?? 8);
|
|
23
|
+
const blocking = getBlockingReminders(reminders);
|
|
24
|
+
const confidence = computeConfidence(puzzle, risk, preferenceMatch);
|
|
25
|
+
return {
|
|
26
|
+
service_id: puzzle.service_id,
|
|
27
|
+
risk,
|
|
28
|
+
industry,
|
|
29
|
+
strategies,
|
|
30
|
+
preference_match: preferenceMatch,
|
|
31
|
+
industry_risks: industryRisks,
|
|
32
|
+
reminders,
|
|
33
|
+
blocking_reminders: blocking,
|
|
34
|
+
confidence,
|
|
35
|
+
summary: buildSummary(puzzle, risk, industry, strategies, preferenceMatch, blocking, confidence),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function toMatchingService(puzzle, risk, overrides) {
|
|
39
|
+
const basics = puzzle.service_basics;
|
|
40
|
+
const fund = puzzle.fund_safety;
|
|
41
|
+
const trust = puzzle.trust_signals;
|
|
42
|
+
const behavior = puzzle.merchant_behavior;
|
|
43
|
+
return {
|
|
44
|
+
service_id: puzzle.service_id,
|
|
45
|
+
price: basics.price_raw,
|
|
46
|
+
token_type: basics.token_type ?? "",
|
|
47
|
+
avg_market_price: puzzle.market_context?.avg_price,
|
|
48
|
+
merchant_order_history_count: behavior?.total_orders ?? 0,
|
|
49
|
+
merchant_age: behavior
|
|
50
|
+
? behavior.total_orders >= 50 ? "established" : "emerging"
|
|
51
|
+
: "unknown",
|
|
52
|
+
has_arbitration: (trust?.arbitration_count ?? 0) > 0,
|
|
53
|
+
has_compensation_fund: fund ? fund.compensation_ratio > 0 : false,
|
|
54
|
+
has_reward_activity: false,
|
|
55
|
+
has_discount: false,
|
|
56
|
+
risk_score: risk.total,
|
|
57
|
+
trust_score: trust?.trust_score ?? 50,
|
|
58
|
+
requires_messenger: false,
|
|
59
|
+
after_sales_support_level: trust?.has_messenger ? "full" : "minimal",
|
|
60
|
+
...overrides,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function buildReminderContext(puzzle, risk, overrides) {
|
|
64
|
+
const trust = puzzle.trust_signals;
|
|
65
|
+
const fund = puzzle.fund_safety;
|
|
66
|
+
const wf = puzzle.workflow_analysis;
|
|
67
|
+
return {
|
|
68
|
+
stage: "preorder",
|
|
69
|
+
service_id: puzzle.service_id,
|
|
70
|
+
review_count: trust?.review_total,
|
|
71
|
+
like_rate: trust?.like_rate,
|
|
72
|
+
avg_market_price: puzzle.market_context?.avg_price,
|
|
73
|
+
service_price: puzzle.service_basics.price_raw,
|
|
74
|
+
token: registryDisplayHint(puzzle.service_basics.token_type),
|
|
75
|
+
has_arbitration: (trust?.arbitration_count ?? 0) > 0,
|
|
76
|
+
has_compensation: fund ? fund.compensation_ratio > 0 : undefined,
|
|
77
|
+
compensation_ratio: fund?.compensation_ratio,
|
|
78
|
+
risk_score: risk.total,
|
|
79
|
+
risk_level: risk.level,
|
|
80
|
+
has_refund_path: wf?.has_refund_path,
|
|
81
|
+
has_messenger: trust?.has_messenger,
|
|
82
|
+
...overrides,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function computeConfidence(puzzle, risk, match) {
|
|
86
|
+
const base = Math.max(0, Math.min(100, 100 - risk.total));
|
|
87
|
+
const userAdj = puzzle.user_metrics?.adjustment ?? 0;
|
|
88
|
+
const prefNudge = match ? Math.round((match.score - 50) / 10) : 0;
|
|
89
|
+
const score = Math.max(0, Math.min(100, base + userAdj + prefNudge));
|
|
90
|
+
const parts = [`base ${base} (= 100 - risk ${risk.total})`];
|
|
91
|
+
if (userAdj !== 0)
|
|
92
|
+
parts.push(`your custom metrics ${userAdj > 0 ? "+" : ""}${userAdj}`);
|
|
93
|
+
if (prefNudge !== 0)
|
|
94
|
+
parts.push(`preference fit ${prefNudge > 0 ? "+" : ""}${prefNudge}`);
|
|
95
|
+
return {
|
|
96
|
+
score,
|
|
97
|
+
base,
|
|
98
|
+
user_adjustment: userAdj,
|
|
99
|
+
preference_nudge: prefNudge,
|
|
100
|
+
explanation: `Confidence ${score}/100 = ${parts.join(" ")}. ` +
|
|
101
|
+
`This is evidence aggregation, not advice — the decision is yours.`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function buildSummary(puzzle, risk, industry, strategies, match, blocking, confidence) {
|
|
105
|
+
const parts = [
|
|
106
|
+
`Order confidence ${confidence.score}/100 (risk ${risk.total}/100, level ${risk.level})` +
|
|
107
|
+
(industry ? ` for ${industry} service` : "") +
|
|
108
|
+
`. Information completeness ${Math.round(puzzle.completeness * 100)}%.`,
|
|
109
|
+
];
|
|
110
|
+
if (blocking.length > 0) {
|
|
111
|
+
parts.push(`⚠️ ${blocking.length} blocking concern(s): ${blocking.map(r => r.message).join("; ")}`);
|
|
112
|
+
}
|
|
113
|
+
if (risk.red_flags.length > 0) {
|
|
114
|
+
parts.push(`Red flags: ${risk.red_flags.slice(0, 3).join("; ")}.`);
|
|
115
|
+
}
|
|
116
|
+
if (strategies.length > 0) {
|
|
117
|
+
const top = strategies[0];
|
|
118
|
+
parts.push(`Key protection (${top.scenario}): ${top.strategy.user_strategy}`);
|
|
119
|
+
}
|
|
120
|
+
if (match) {
|
|
121
|
+
parts.push(match.mismatches.length > 0
|
|
122
|
+
? `Preference mismatches: ${match.mismatches.slice(0, 2).join("; ")}.`
|
|
123
|
+
: `Service matches your preferences (score ${match.score}/100).`);
|
|
124
|
+
}
|
|
125
|
+
if (puzzle.gaps.length > 0) {
|
|
126
|
+
parts.push(`Missing information: ${puzzle.gaps.join(", ")} — consider asking the merchant via Messenger before ordering.`);
|
|
127
|
+
}
|
|
128
|
+
return parts.join(" ");
|
|
129
|
+
}
|
package/dist/customer/index.d.ts
CHANGED
|
@@ -7,3 +7,5 @@ export { monitorOrder, sortAlerts, getCriticalAlerts, getActionableAlerts, summa
|
|
|
7
7
|
export { recommendStrategy, detectScenarios, flowMigrationStrategy, repeatGameStrategy, rightsProtectionStrategy, type StrategyContext, type StrategyRecommendation, } from "./order-strategy.js";
|
|
8
8
|
export { generatePostPurchaseAdvice, trackRefund, handleQualityIssue, handleMerchantUnreachable, arbitrationSupport, generateArbitrationTemplate, type PostPurchasePhase, type PostPurchaseContext, type PostPurchaseAction, } from "./post-purchase.js";
|
|
9
9
|
export { generateReminders, sortAndCapReminders, generateMultiStageReminders, isBlocking, getBlockingReminders, summarizeReminders, topReminders, type ReminderStage, type ReminderContext, } from "./reminder-system.js";
|
|
10
|
+
export { assemblePreorderAdvice, type PreorderAdviceInput, type PreorderAdvice, type ConfidenceScore, } from "./customer-advice.js";
|
|
11
|
+
export { buildPreorderComparison, type PreorderCompareRow, type PreorderComparison, } from "./preorder-compare.js";
|
package/dist/customer/index.js
CHANGED
|
@@ -7,3 +7,5 @@ export { monitorOrder, sortAlerts, getCriticalAlerts, getActionableAlerts, summa
|
|
|
7
7
|
export { recommendStrategy, detectScenarios, flowMigrationStrategy, repeatGameStrategy, rightsProtectionStrategy, } from "./order-strategy.js";
|
|
8
8
|
export { generatePostPurchaseAdvice, trackRefund, handleQualityIssue, handleMerchantUnreachable, arbitrationSupport, generateArbitrationTemplate, } from "./post-purchase.js";
|
|
9
9
|
export { generateReminders, sortAndCapReminders, generateMultiStageReminders, isBlocking, getBlockingReminders, summarizeReminders, topReminders, } from "./reminder-system.js";
|
|
10
|
+
export { assemblePreorderAdvice, } from "./customer-advice.js";
|
|
11
|
+
export { buildPreorderComparison, } from "./preorder-compare.js";
|
|
@@ -65,12 +65,15 @@ export declare function assembleFundSafety(raw: ServiceRawData, orderAmount: big
|
|
|
65
65
|
export declare function assembleTrustSignals(service: ServiceRawData, reviews: ReviewRaw[], trustScore: {
|
|
66
66
|
score: number;
|
|
67
67
|
level: string;
|
|
68
|
-
}, arbitrationOwner?: string, serviceOwner?: string): TrustSignals;
|
|
68
|
+
}, arbitrationOwner?: string, serviceOwner?: string, permissionShared?: boolean, permissionOverlap?: boolean): TrustSignals;
|
|
69
69
|
export declare function assembleMerchantBehavior(events: EventRaw[], orderHistory?: Array<{
|
|
70
70
|
status: string;
|
|
71
71
|
has_dispute: boolean;
|
|
72
72
|
is_repeat: boolean;
|
|
73
|
-
}
|
|
73
|
+
}>, reputation?: {
|
|
74
|
+
likes: number;
|
|
75
|
+
dislikes: number;
|
|
76
|
+
}): MerchantBehavior;
|
|
74
77
|
export declare function assembleMarketContext(similarServices: Array<{
|
|
75
78
|
price: bigint;
|
|
76
79
|
}>, currentPrice: bigint): MarketContext;
|
|
@@ -97,6 +100,10 @@ export interface PuzzleRawData {
|
|
|
97
100
|
has_dispute: boolean;
|
|
98
101
|
is_repeat: boolean;
|
|
99
102
|
}>;
|
|
103
|
+
merchant_reputation?: {
|
|
104
|
+
likes: number;
|
|
105
|
+
dislikes: number;
|
|
106
|
+
};
|
|
100
107
|
user_metrics_config?: UserMetricsConfig;
|
|
101
108
|
user_metrics_context?: Record<string, unknown>;
|
|
102
109
|
service_nesting_raw?: ServiceNestingRawData;
|
|
@@ -32,8 +32,8 @@ export function assembleWorkflowAnalysis(nodes, isPublished, isPaused, serviceRa
|
|
|
32
32
|
let hasMilestone = false;
|
|
33
33
|
let hasWonderNode = false;
|
|
34
34
|
let hasDisputeAntiPattern = false;
|
|
35
|
-
const antiPatternNodeRegex =
|
|
36
|
-
const wonderNodeRegex = /^(wonder|no_wonder|praise|complain|thumbs_up|thumbs_down
|
|
35
|
+
const antiPatternNodeRegex = /(^|_)(disputed?|refund(?:ed)?|arbitration|arb)(_|$)/i;
|
|
36
|
+
const wonderNodeRegex = /^(wonder|no_wonder|praise|complain|thumbs_up|thumbs_down|positive_review|negative_review)$/i;
|
|
37
37
|
const totalForwards = nodes.reduce((sum, n) => sum + (n.forwards?.length ?? 0), 0);
|
|
38
38
|
for (const node of nodes) {
|
|
39
39
|
if (antiPatternNodeRegex.test(node.name.trim())) {
|
|
@@ -146,7 +146,7 @@ export function assembleFundSafety(raw, orderAmount) {
|
|
|
146
146
|
price_anomaly: priceAnomaly,
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
-
export function assembleTrustSignals(service, reviews, trustScore, arbitrationOwner, serviceOwner) {
|
|
149
|
+
export function assembleTrustSignals(service, reviews, trustScore, arbitrationOwner, serviceOwner, permissionShared, permissionOverlap) {
|
|
150
150
|
const likes = reviews.filter((r) => r.rating === "like").length;
|
|
151
151
|
const dislikes = reviews.filter((r) => r.rating === "dislike").length;
|
|
152
152
|
const verified = reviews.filter((r) => r.verified || r.has_evidence).length;
|
|
@@ -168,9 +168,31 @@ export function assembleTrustSignals(service, reviews, trustScore, arbitrationOw
|
|
|
168
168
|
trust_level: trustScore.level,
|
|
169
169
|
has_contact: !!service.um,
|
|
170
170
|
has_messenger: !!service.um,
|
|
171
|
+
arbitration_permission_shared: permissionShared,
|
|
172
|
+
arbitration_permission_overlap: permissionOverlap,
|
|
171
173
|
};
|
|
172
174
|
}
|
|
173
|
-
|
|
175
|
+
const REPUTATION_MIN_VOTES = 3;
|
|
176
|
+
function toReputation(rep) {
|
|
177
|
+
const total = rep.likes + rep.dislikes;
|
|
178
|
+
return {
|
|
179
|
+
likes: rep.likes,
|
|
180
|
+
dislikes: rep.dislikes,
|
|
181
|
+
like_ratio: total > 0 ? rep.likes / total : 1,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function reputationRedFlags(rep) {
|
|
185
|
+
if (!rep)
|
|
186
|
+
return [];
|
|
187
|
+
const total = rep.likes + rep.dislikes;
|
|
188
|
+
if (total >= REPUTATION_MIN_VOTES && rep.like_ratio < 0.5) {
|
|
189
|
+
return ["reputation_negative"];
|
|
190
|
+
}
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
export function assembleMerchantBehavior(events, orderHistory, reputation) {
|
|
194
|
+
const rep = reputation ? toReputation(reputation) : undefined;
|
|
195
|
+
const repFlags = reputationRedFlags(rep);
|
|
174
196
|
if (orderHistory && orderHistory.length > 0) {
|
|
175
197
|
const total = orderHistory.length;
|
|
176
198
|
const completed = orderHistory.filter((o) => o.status === "completed").length;
|
|
@@ -191,7 +213,7 @@ export function assembleMerchantBehavior(events, orderHistory) {
|
|
|
191
213
|
else if (secondRate > firstRate * 1.15)
|
|
192
214
|
trend = "declining";
|
|
193
215
|
}
|
|
194
|
-
const redFlags = [];
|
|
216
|
+
const redFlags = [...repFlags];
|
|
195
217
|
if (disputeRate > 0.1)
|
|
196
218
|
redFlags.push("dispute_rate_high");
|
|
197
219
|
if (trend === "declining")
|
|
@@ -205,6 +227,7 @@ export function assembleMerchantBehavior(events, orderHistory) {
|
|
|
205
227
|
repeat_buyer_rate: repeatRate,
|
|
206
228
|
recent_trend: trend,
|
|
207
229
|
red_flags: redFlags,
|
|
230
|
+
reputation: rep,
|
|
208
231
|
};
|
|
209
232
|
}
|
|
210
233
|
const orderEvents = events.filter((e) => e.type.includes("Order") || e.type.includes("order"));
|
|
@@ -212,7 +235,7 @@ export function assembleMerchantBehavior(events, orderHistory) {
|
|
|
212
235
|
const total = orderEvents.length;
|
|
213
236
|
const disputes = disputeEvents.length;
|
|
214
237
|
const disputeRate = total > 0 ? disputes / total : 0;
|
|
215
|
-
const redFlags = [];
|
|
238
|
+
const redFlags = [...repFlags];
|
|
216
239
|
if (disputeRate > 0.1)
|
|
217
240
|
redFlags.push("dispute_rate_high");
|
|
218
241
|
return {
|
|
@@ -224,6 +247,7 @@ export function assembleMerchantBehavior(events, orderHistory) {
|
|
|
224
247
|
repeat_buyer_rate: 0,
|
|
225
248
|
recent_trend: "stable",
|
|
226
249
|
red_flags: redFlags,
|
|
250
|
+
reputation: rep,
|
|
227
251
|
};
|
|
228
252
|
}
|
|
229
253
|
export function assembleMarketContext(similarServices, currentPrice) {
|
|
@@ -282,7 +306,10 @@ export function assembleInfoPuzzle(serviceId, raw, depth = "evaluate") {
|
|
|
282
306
|
let merchantBehavior;
|
|
283
307
|
if (depth === "preorder" || depth === "monitor") {
|
|
284
308
|
if (raw.events || raw.order_history) {
|
|
285
|
-
merchantBehavior = assembleMerchantBehavior(raw.events ?? [], raw.order_history);
|
|
309
|
+
merchantBehavior = assembleMerchantBehavior(raw.events ?? [], raw.order_history, raw.merchant_reputation);
|
|
310
|
+
}
|
|
311
|
+
else if (raw.merchant_reputation) {
|
|
312
|
+
merchantBehavior = assembleMerchantBehavior([], undefined, raw.merchant_reputation);
|
|
286
313
|
}
|
|
287
314
|
else {
|
|
288
315
|
gaps.push("merchant_behavior");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { RiskLevel } from "./types.js";
|
|
2
2
|
import { CUSTOMER_INTELLIGENCE_VERSION } from "./types.js";
|
|
3
|
+
import { type TokenDisplayHint } from "../knowledge/fund-layer.js";
|
|
3
4
|
export type AlertSeverity = "info" | "warning" | "critical";
|
|
4
5
|
export type AlertCategory = "progress_stall" | "compensation_drop" | "compensation_insufficient" | "messenger_timeout" | "user_action_required" | "review_window" | "arb_window" | "refund_received" | "anomaly";
|
|
5
6
|
export interface MonitorAlert {
|
|
@@ -30,6 +31,7 @@ export interface OrderSnapshot {
|
|
|
30
31
|
expected_progress_hours?: number;
|
|
31
32
|
order_amount?: bigint;
|
|
32
33
|
compensation_balance?: bigint;
|
|
34
|
+
token?: TokenDisplayHint;
|
|
33
35
|
has_arbitration?: boolean;
|
|
34
36
|
has_messenger?: boolean;
|
|
35
37
|
last_merchant_reply_at?: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CUSTOMER_INTELLIGENCE_VERSION } from "./types.js";
|
|
2
|
+
import { formatAmountText } from "../knowledge/fund-layer.js";
|
|
2
3
|
const DEFAULT_THRESHOLDS = {
|
|
3
4
|
progress_stall_hours: 0,
|
|
4
5
|
compensation_drop_ratio: 0.3,
|
|
@@ -118,7 +119,7 @@ function detectCompensationChange(cur, prev, t) {
|
|
|
118
119
|
category: "compensation_insufficient",
|
|
119
120
|
severity,
|
|
120
121
|
title: "Compensation fund coverage insufficient",
|
|
121
|
-
message: `Merchant compensation fund covers only ${Math.round(ratio * 100)}% of the order amount (required ${Math.round(t.compensation_coverage_min * 100)}%)`,
|
|
122
|
+
message: `Merchant compensation fund covers only ${Math.round(ratio * 100)}% of the order amount (required ${Math.round(t.compensation_coverage_min * 100)}%): fund ${formatAmountText(cur.compensation_balance, cur.token?.decimals, cur.token?.symbol)} vs order ${formatAmountText(cur.order_amount, cur.token?.decimals, cur.token?.symbol)}`,
|
|
122
123
|
action: "Require the merchant to top up the compensation fund before ordering, or negotiate higher coverage via Messenger",
|
|
123
124
|
timestamp: cur.now,
|
|
124
125
|
order_id: cur.order_id,
|
|
@@ -143,7 +144,7 @@ function detectCompensationChange(cur, prev, t) {
|
|
|
143
144
|
category: "compensation_drop",
|
|
144
145
|
severity,
|
|
145
146
|
title: "Compensation fund balance dropped significantly",
|
|
146
|
-
message: `Merchant compensation fund dropped from ${prevBal} to ${cur.compensation_balance} (down ${Math.round(dropRatio * 100)}%)`,
|
|
147
|
+
message: `Merchant compensation fund dropped from ${formatAmountText(prevBal, cur.token?.decimals, cur.token?.symbol)} to ${formatAmountText(cur.compensation_balance, cur.token?.decimals, cur.token?.symbol)} (down ${Math.round(dropRatio * 100)}%)`,
|
|
147
148
|
action: "Immediately ask the merchant for the reason; if it keeps dropping, the merchant may be processing payouts for other orders, which is a risk",
|
|
148
149
|
timestamp: cur.now,
|
|
149
150
|
order_id: cur.order_id,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { InfoPuzzle } from "./types.js";
|
|
2
2
|
import { CUSTOMER_INTELLIGENCE_VERSION } from "./types.js";
|
|
3
|
+
import { type TokenDisplayHint } from "../knowledge/fund-layer.js";
|
|
3
4
|
export type PostPurchasePhase = "refund_tracking" | "quality_issue" | "merchant_unreachable" | "arbitration_support";
|
|
4
5
|
export interface PostPurchaseContext {
|
|
5
6
|
phase: PostPurchasePhase;
|
|
@@ -8,6 +9,7 @@ export interface PostPurchaseContext {
|
|
|
8
9
|
puzzle?: InfoPuzzle;
|
|
9
10
|
order_amount?: bigint;
|
|
10
11
|
refunded_amount?: bigint;
|
|
12
|
+
token?: TokenDisplayHint;
|
|
11
13
|
wip_hash?: string;
|
|
12
14
|
original_wip_hash?: string;
|
|
13
15
|
last_merchant_reply_at?: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CUSTOMER_INTELLIGENCE_VERSION } from "./types.js";
|
|
2
|
+
import { formatAmountText } from "../knowledge/fund-layer.js";
|
|
2
3
|
export function generatePostPurchaseAdvice(ctx) {
|
|
3
4
|
switch (ctx.phase) {
|
|
4
5
|
case "refund_tracking":
|
|
@@ -21,7 +22,7 @@ export function trackRefund(ctx) {
|
|
|
21
22
|
phase: "refund_tracking",
|
|
22
23
|
priority: "info",
|
|
23
24
|
title: "Refund complete",
|
|
24
|
-
message: `✅ Order ${ctx.order_id} refund fully received (${refunded
|
|
25
|
+
message: `✅ Order ${ctx.order_id} refund fully received (${formatAmountText(refunded, ctx.token?.decimals, ctx.token?.symbol)})`,
|
|
25
26
|
next_step: "You can close post-purchase tracking; recommend submitting an order review",
|
|
26
27
|
});
|
|
27
28
|
return actions;
|
|
@@ -33,7 +34,7 @@ export function trackRefund(ctx) {
|
|
|
33
34
|
phase: "refund_tracking",
|
|
34
35
|
priority: "required",
|
|
35
36
|
title: "Refund incomplete",
|
|
36
|
-
message: `⚠️ Order ${ctx.order_id} only refunded ${refunded}
|
|
37
|
+
message: `⚠️ Order ${ctx.order_id} only refunded ${formatAmountText(refunded, ctx.token?.decimals, ctx.token?.symbol)} of ${formatAmountText(orderAmount, ctx.token?.decimals, ctx.token?.symbol)}; the difference of ${formatAmountText(diff, ctx.token?.decimals, ctx.token?.symbol)} has not been received`,
|
|
37
38
|
next_step: "Urge the merchant via Messenger to make up the difference, or initiate arbitration to recover it",
|
|
38
39
|
tool: "messenger_send",
|
|
39
40
|
});
|
|
@@ -284,7 +285,7 @@ export function generateArbitrationTemplate(ctx) {
|
|
|
284
285
|
descriptionParts.push(`Dispute type: ${phaseLabel}`);
|
|
285
286
|
switch (ctx.phase) {
|
|
286
287
|
case "refund_tracking":
|
|
287
|
-
descriptionParts.push(`Dispute summary: The merchant did not refund as required. Order amount ${ctx.order_amount
|
|
288
|
+
descriptionParts.push(`Dispute summary: The merchant did not refund as required. Order amount ${ctx.order_amount !== undefined ? formatAmountText(ctx.order_amount, ctx.token?.decimals, ctx.token?.symbol) : "unknown"}, refunded ${formatAmountText(ctx.refunded_amount ?? 0n, ctx.token?.decimals, ctx.token?.symbol)}.`);
|
|
288
289
|
break;
|
|
289
290
|
case "quality_issue":
|
|
290
291
|
descriptionParts.push(`Dispute summary: The deliverable has quality issues. Original WIP hash: ${ctx.original_wip_hash ?? "unknown"}, current: ${ctx.wip_hash ?? "unknown"}.`);
|
|
@@ -335,9 +336,9 @@ function buildClaim(ctx) {
|
|
|
335
336
|
const refunded = ctx.refunded_amount ?? 0n;
|
|
336
337
|
const diff = orderAmount - refunded;
|
|
337
338
|
if (refunded === 0n) {
|
|
338
|
-
return `Request the arbitrator to order a full refund (${orderAmount
|
|
339
|
+
return `Request the arbitrator to order a full refund (${formatAmountText(orderAmount, ctx.token?.decimals, ctx.token?.symbol)}).`;
|
|
339
340
|
}
|
|
340
|
-
return `Request the arbitrator to order the merchant to make up the refund difference (${diff
|
|
341
|
+
return `Request the arbitrator to order the merchant to make up the refund difference (${formatAmountText(diff, ctx.token?.decimals, ctx.token?.symbol)}).`;
|
|
341
342
|
}
|
|
342
343
|
case "quality_issue":
|
|
343
344
|
return "Request the arbitrator to order the merchant to redeliver a deliverable that meets the agreement, or to fully refund.";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface PreorderCompareRow {
|
|
2
|
+
service_id: string;
|
|
3
|
+
service_name: string;
|
|
4
|
+
error?: string;
|
|
5
|
+
industry?: string;
|
|
6
|
+
confidence?: number;
|
|
7
|
+
risk_total?: number;
|
|
8
|
+
risk_level?: string;
|
|
9
|
+
trust_score?: number;
|
|
10
|
+
trust_level?: string;
|
|
11
|
+
preference_match?: number;
|
|
12
|
+
reputation_like_ratio?: number;
|
|
13
|
+
reputation_votes?: number;
|
|
14
|
+
red_flags_count?: number;
|
|
15
|
+
blocking_reminders_count?: number;
|
|
16
|
+
info_gaps_count?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface PreorderComparison {
|
|
19
|
+
rows: PreorderCompareRow[];
|
|
20
|
+
best_per_metric: Record<string, string[]>;
|
|
21
|
+
evaluated_metrics: string[];
|
|
22
|
+
note: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function buildPreorderComparison(rows: PreorderCompareRow[]): PreorderComparison;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const METRICS = [
|
|
2
|
+
{ key: "confidence", name: "confidence", direction: "high" },
|
|
3
|
+
{ key: "risk_total", name: "risk_total", direction: "low" },
|
|
4
|
+
{ key: "trust_score", name: "trust_score", direction: "high" },
|
|
5
|
+
{ key: "preference_match", name: "preference_match", direction: "high" },
|
|
6
|
+
{ key: "reputation_like_ratio", name: "reputation_like_ratio", direction: "high" },
|
|
7
|
+
{ key: "red_flags_count", name: "red_flags_count", direction: "low" },
|
|
8
|
+
{ key: "blocking_reminders_count", name: "blocking_reminders_count", direction: "low" },
|
|
9
|
+
{ key: "info_gaps_count", name: "info_gaps_count", direction: "low" },
|
|
10
|
+
];
|
|
11
|
+
const NEUTRALITY_NOTE = "Per-metric bests only — NO overall ranking is computed. " +
|
|
12
|
+
"Metric weights are the buyer's own: re-run with user_metrics to change what matters. " +
|
|
13
|
+
"A service 'best' on one metric may be worst on another; the decision is yours.";
|
|
14
|
+
export function buildPreorderComparison(rows) {
|
|
15
|
+
const best_per_metric = {};
|
|
16
|
+
const evaluated_metrics = [];
|
|
17
|
+
for (const m of METRICS) {
|
|
18
|
+
const candidates = rows.filter((r) => !r.error && typeof r[m.key] === "number");
|
|
19
|
+
if (candidates.length < 2)
|
|
20
|
+
continue;
|
|
21
|
+
const values = candidates.map((r) => r[m.key]);
|
|
22
|
+
const best = m.direction === "high" ? Math.max(...values) : Math.min(...values);
|
|
23
|
+
best_per_metric[m.name] = candidates
|
|
24
|
+
.filter((r) => r[m.key] === best)
|
|
25
|
+
.map((r) => r.service_id);
|
|
26
|
+
evaluated_metrics.push(m.name);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
rows,
|
|
30
|
+
best_per_metric,
|
|
31
|
+
evaluated_metrics,
|
|
32
|
+
note: NEUTRALITY_NOTE,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Reminder, RiskLevel } from "./types.js";
|
|
2
2
|
import { CUSTOMER_INTELLIGENCE_VERSION } from "./types.js";
|
|
3
|
+
import { type TokenDisplayHint } from "../knowledge/fund-layer.js";
|
|
3
4
|
export type ReminderStage = "browse" | "evaluate" | "preorder" | "in_progress" | "complete" | "after_sale";
|
|
4
5
|
export interface ReminderContext {
|
|
5
6
|
stage: ReminderStage;
|
|
@@ -13,6 +14,7 @@ export interface ReminderContext {
|
|
|
13
14
|
has_compensation?: boolean;
|
|
14
15
|
compensation_balance?: bigint;
|
|
15
16
|
compensation_ratio?: number;
|
|
17
|
+
token?: TokenDisplayHint;
|
|
16
18
|
risk_score?: number;
|
|
17
19
|
risk_level?: RiskLevel;
|
|
18
20
|
has_refund_path?: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CUSTOMER_INTELLIGENCE_VERSION } from "./types.js";
|
|
2
|
+
import { formatAmountText } from "../knowledge/fund-layer.js";
|
|
2
3
|
const REMINDER_RULES = [
|
|
3
4
|
{
|
|
4
5
|
id: "browse_reviews_summary",
|
|
@@ -108,7 +109,7 @@ const REMINDER_RULES = [
|
|
|
108
109
|
id: "preorder_payment_confirm",
|
|
109
110
|
stage: "preorder",
|
|
110
111
|
priority: "required",
|
|
111
|
-
message: (ctx) => `🔔 About to pay ${ctx.service_price
|
|
112
|
+
message: (ctx) => `🔔 About to pay ${formatAmountText(ctx.service_price ?? 0n, ctx.token?.decimals, ctx.token?.symbol)} to the escrow account, please confirm`,
|
|
112
113
|
applies: (ctx) => ctx.service_price !== undefined,
|
|
113
114
|
dedup_key: "payment_confirm",
|
|
114
115
|
},
|
|
@@ -134,13 +134,35 @@ function assessTrustRisk(puzzle) {
|
|
|
134
134
|
const trust = puzzle.trust_signals;
|
|
135
135
|
const checks = [];
|
|
136
136
|
const arbIndependent = trust?.arbitration_independent ?? true;
|
|
137
|
+
const permShared = trust?.arbitration_permission_shared === true;
|
|
138
|
+
const permOverlap = trust?.arbitration_permission_overlap === true;
|
|
139
|
+
let arbPassed = arbIndependent;
|
|
140
|
+
let arbAdvice;
|
|
141
|
+
let arbWeight = 6;
|
|
142
|
+
if (permShared) {
|
|
143
|
+
arbPassed = false;
|
|
144
|
+
arbAdvice = "🔴 CRITICAL: Arbitration and Service share the SAME Permission object. " +
|
|
145
|
+
"The merchant fully controls arbitration operations (vote, confirm, execute rulings). " +
|
|
146
|
+
"Dispute fairness cannot be guaranteed. Require the merchant to use a separate, " +
|
|
147
|
+
"independent Permission object for Arbitration before ordering.";
|
|
148
|
+
}
|
|
149
|
+
else if (permOverlap) {
|
|
150
|
+
arbPassed = false;
|
|
151
|
+
arbAdvice = "🔴 WARNING: Arbitration and Service have overlapping Permission control " +
|
|
152
|
+
"(shared owner or admin). Even with separate Permission objects, the merchant can " +
|
|
153
|
+
"influence dispute outcomes. For mainnet, require completely independent third-party " +
|
|
154
|
+
"Permission (different owner and admin list) for Arbitration.";
|
|
155
|
+
}
|
|
156
|
+
else if (!arbIndependent) {
|
|
157
|
+
arbAdvice = "🔴 Arbitrator and merchant are the same address: arbitration fairness cannot be guaranteed.";
|
|
158
|
+
}
|
|
137
159
|
checks.push({
|
|
138
160
|
id: "trust_arb_independent",
|
|
139
161
|
dimension: "trust",
|
|
140
|
-
description: "Arbitrator has no conflict of interest with the merchant",
|
|
141
|
-
weight:
|
|
142
|
-
passed:
|
|
143
|
-
advice:
|
|
162
|
+
description: "Arbitrator has no conflict of interest with the merchant (Permission isolation)",
|
|
163
|
+
weight: arbWeight,
|
|
164
|
+
passed: arbPassed,
|
|
165
|
+
advice: arbAdvice,
|
|
144
166
|
});
|
|
145
167
|
let reviewPassed = false;
|
|
146
168
|
let reviewAdvice;
|
|
@@ -223,7 +245,8 @@ function assessBehaviorRisk(puzzle) {
|
|
|
223
245
|
passed: trendPassed,
|
|
224
246
|
advice: trendAdvice,
|
|
225
247
|
});
|
|
226
|
-
const
|
|
248
|
+
const hasOrders = beh != null && beh.total_orders > 0;
|
|
249
|
+
const completionPassed = hasOrders ? beh.completed_rate >= 0.85 : true;
|
|
227
250
|
checks.push({
|
|
228
251
|
id: "behavior_completion_rate",
|
|
229
252
|
dimension: "behavior",
|
|
@@ -232,7 +255,7 @@ function assessBehaviorRisk(puzzle) {
|
|
|
232
255
|
passed: completionPassed,
|
|
233
256
|
advice: completionPassed ? undefined : `🔴 Completion rate is only ${Math.round((beh?.completed_rate ?? 0) * 100)}%: a higher-than-average share of orders end in failure.`,
|
|
234
257
|
});
|
|
235
|
-
const disputeOk =
|
|
258
|
+
const disputeOk = hasOrders ? beh.dispute_rate <= 0.1 : true;
|
|
236
259
|
checks.push({
|
|
237
260
|
id: "behavior_low_dispute",
|
|
238
261
|
dimension: "behavior",
|
|
@@ -241,7 +264,7 @@ function assessBehaviorRisk(puzzle) {
|
|
|
241
264
|
passed: disputeOk,
|
|
242
265
|
advice: disputeOk ? undefined : `⚠️ Dispute rate is ${Math.round((beh?.dispute_rate ?? 0) * 100)}%: above the industry average.`,
|
|
243
266
|
});
|
|
244
|
-
const arbLossOk =
|
|
267
|
+
const arbLossOk = hasOrders ? beh.arb_loss_rate <= 0.3 : true;
|
|
245
268
|
checks.push({
|
|
246
269
|
id: "behavior_arb_loss",
|
|
247
270
|
dimension: "behavior",
|
package/dist/customer/types.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export interface TrustSignals {
|
|
|
61
61
|
trust_level: "high_risk" | "caution" | "moderate" | "trusted";
|
|
62
62
|
has_contact: boolean;
|
|
63
63
|
has_messenger: boolean;
|
|
64
|
+
arbitration_permission_shared?: boolean;
|
|
65
|
+
arbitration_permission_overlap?: boolean;
|
|
64
66
|
}
|
|
65
67
|
export interface MerchantBehavior {
|
|
66
68
|
total_orders: number;
|
|
@@ -71,6 +73,11 @@ export interface MerchantBehavior {
|
|
|
71
73
|
repeat_buyer_rate: number;
|
|
72
74
|
recent_trend: "improving" | "stable" | "declining";
|
|
73
75
|
red_flags: string[];
|
|
76
|
+
reputation?: {
|
|
77
|
+
likes: number;
|
|
78
|
+
dislikes: number;
|
|
79
|
+
like_ratio: number;
|
|
80
|
+
};
|
|
74
81
|
}
|
|
75
82
|
export interface MarketContext {
|
|
76
83
|
similar_services_count: number;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Open Dispute on an Order (Arbitration Case Creation)",
|
|
3
|
+
"description": "Customer opens a dispute on order myshop_order_v1 via the MyShop Arbitration object, paying the dispute fee and naming the new Arb case object for later vote/verdict operations.",
|
|
4
|
+
"tags": ["arbitration", "dispute", "order", "retail"],
|
|
5
|
+
"industry": "retail",
|
|
6
|
+
"operation_type": "arbitration",
|
|
7
|
+
"source": "constructed under T-09 authorization; grounded in DisputeSchema + SDK arbitration.ts dispute flow + arb.move dispute_imp — schema-validated, not chain-verified",
|
|
8
|
+
"verified": false,
|
|
9
|
+
"network": "testnet",
|
|
10
|
+
"call": {
|
|
11
|
+
"tool": "onchain_operations",
|
|
12
|
+
"operation_type": "arbitration",
|
|
13
|
+
"data": {
|
|
14
|
+
"object": "myshop_arbitration_v2",
|
|
15
|
+
"dispute": {
|
|
16
|
+
"order": "myshop_order_v1",
|
|
17
|
+
"description": "Toy arrived damaged; requesting refund per service promise.",
|
|
18
|
+
"proposition": [
|
|
19
|
+
"Full refund to customer",
|
|
20
|
+
"Partial refund 50%",
|
|
21
|
+
"No refund — service delivered as promised"
|
|
22
|
+
],
|
|
23
|
+
"fee": { "balance": 5000000 },
|
|
24
|
+
"namedArb": { "name": "myshop_dispute_v1" }
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"env": {
|
|
28
|
+
"network": "testnet",
|
|
29
|
+
"no_cache": true,
|
|
30
|
+
"confirmed": true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"notes": [
|
|
34
|
+
"PREREQUISITES (SDK-validated client-side): the Arbitration must NOT be paused (bPaused=false — new Arbitrations are created paused; unpause first via {object:'myshop_arbitration_v2', pause:false}); the Order must not be already claimed (claimed_by empty) and must have fewer than MAX_DISPUTE_COUNT disputes.",
|
|
35
|
+
"fee uses CoinParam {balance: <smallest unit>} — 5000000 = 0.005 WOW (9 decimals). Contract asserts fee >= arbitration.fee (E_FEE_NOT_ENOUGH); excess is split and returned to the sender.",
|
|
36
|
+
"proposition is the list of options voters choose between; votes reference propositions by 0-BASED INDEX (0='Full refund', 1='Partial 50%', 2='No refund'). Order matters and is immutable once the Arb is created.",
|
|
37
|
+
"namedArb names the NEW Arb (arbitration case) object — strongly recommended: subsequent confirm/vote/arbitration calls reference the case by this name ('myshop_dispute_v1') instead of a raw address.",
|
|
38
|
+
"If the Arbitration has a usage_guard configured, the dispute caller must pass that Guard (SDK auto-adds it to the passport verification list). This example assumes no usage_guard.",
|
|
39
|
+
"The Arb case is created in a pre-voting state; the arbitrator next calls confirm with a voting_deadline to open the voting window."
|
|
40
|
+
]
|
|
41
|
+
}
|