@seasonkoh/webaz 0.1.25 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/layer1-agent/L1-1-mcp-server/server.js +129 -150
- package/dist/layer2-business/L2-9-contribution/build-task-agent-metadata-store.js +9 -0
- package/dist/layer2-business/L2-9-contribution/build-tasks-engine.js +1 -1
- package/dist/layer2-business/L2-9-contribution/identity-claim-discovery.js +55 -0
- package/dist/layer2-business/L2-9-contribution/task-proposal-ai-store.js +99 -0
- package/dist/layer2-business/L2-9-contribution/task-proposal-draft.js +191 -0
- package/dist/pwa/admin-bearer-auth.js +21 -0
- package/dist/pwa/email-delivery.js +127 -0
- package/dist/pwa/public/app.js +940 -245
- package/dist/pwa/public/i18n.js +269 -40
- package/dist/pwa/public/openapi.json +4 -4
- package/dist/pwa/public/whitepaper/en/index.html +153 -0
- package/dist/pwa/public/whitepaper/zh-CN/index.html +153 -0
- package/dist/pwa/routes/admin-atomic.js +10 -4
- package/dist/pwa/routes/admin-moderation.js +25 -1
- package/dist/pwa/routes/admin-ops.js +13 -2
- package/dist/pwa/routes/admin-users-query.js +12 -1
- package/dist/pwa/routes/admin-wallet-ops.js +26 -3
- package/dist/pwa/routes/auction.js +4 -2
- package/dist/pwa/routes/auth-read.js +10 -1
- package/dist/pwa/routes/auth-register.js +82 -12
- package/dist/pwa/routes/contribution-identity.js +17 -0
- package/dist/pwa/routes/growth.js +1 -1
- package/dist/pwa/routes/orders-action.js +19 -13
- package/dist/pwa/routes/profile-credentials.js +7 -4
- package/dist/pwa/routes/profile-placement.js +7 -8
- package/dist/pwa/routes/promoter.js +3 -17
- package/dist/pwa/routes/ratings.js +64 -4
- package/dist/pwa/routes/recover-key.js +58 -19
- package/dist/pwa/routes/referral.js +4 -24
- package/dist/pwa/routes/share-redirects.js +4 -3
- package/dist/pwa/routes/shop-referral.js +6 -5
- package/dist/pwa/routes/shops.js +5 -2
- package/dist/pwa/routes/task-proposals.js +76 -0
- package/dist/pwa/routes/trial.js +4 -2
- package/dist/pwa/routes/users-public.js +2 -12
- package/dist/pwa/routes/wallet-read.js +1 -1
- package/dist/pwa/server.js +67 -9
- package/package.json +31 -3
|
@@ -43,6 +43,15 @@ const TELEMETRY_ENABLED = (process.env.WEBAZ_TELEMETRY ?? 'off').toLowerCase() =
|
|
|
43
43
|
// P0 不迁移任何工具(NETWORK_TOOLS 为空)→ 一切仍走本地 = 零行为变化;P1/P2 逐个把工具名加入集合切到网络。
|
|
44
44
|
const WEBAZ_API_URL = (process.env.WEBAZ_API_URL ?? 'https://webaz.xyz').replace(/\/+$/, '');
|
|
45
45
|
const WEBAZ_API_KEY = process.env.WEBAZ_API_KEY ?? '';
|
|
46
|
+
// F6 (dogfood R2): keyed MCP handlers resolve api_key as explicit args.api_key > env WEBAZ_API_KEY >
|
|
47
|
+
// '' (→ the existing typed API_KEY_REQUIRED guards). Explicit ALWAYS wins; env never overrides an explicit
|
|
48
|
+
// key. Keyless actions (list/discover/detail/suggest/browse/get_campaign…) gate their public branches
|
|
49
|
+
// separately and never call this, so a configured env key does NOT change the public read boundary.
|
|
50
|
+
// The key is never printed/returned/logged.
|
|
51
|
+
export function resolveMcpApiKey(args, envKey = WEBAZ_API_KEY) {
|
|
52
|
+
const explicit = typeof args?.api_key === 'string' ? args.api_key.trim() : '';
|
|
53
|
+
return explicit || envKey;
|
|
54
|
+
}
|
|
46
55
|
const WEBAZ_MODE_ENV = (process.env.WEBAZ_MODE ?? '').toLowerCase();
|
|
47
56
|
// 模式:显式 WEBAZ_MODE 优先;否则有 api_key → network,无 key → network_readonly(装完即见真网络)。
|
|
48
57
|
// network_readonly(L1 onboarding,2026-06-08):无 key 默认。公共读匿名打 webaz.xyz(真 catalog/协议),
|
|
@@ -403,11 +412,11 @@ Skipping is allowed but agent then carries price/stock-race risk itself.`,
|
|
|
403
412
|
inputSchema: {
|
|
404
413
|
type: 'object',
|
|
405
414
|
properties: {
|
|
406
|
-
api_key: { type: 'string', description: "Buyer's api_key" },
|
|
415
|
+
api_key: { type: 'string', description: "Buyer's api_key (or omit and set the WEBAZ_API_KEY env var)" },
|
|
407
416
|
product_id: { type: 'string', description: 'Product ID (from webaz_search)' },
|
|
408
417
|
quantity: { type: 'number', description: 'Quantity, default 1' },
|
|
409
418
|
},
|
|
410
|
-
required: ['
|
|
419
|
+
required: ['product_id'],
|
|
411
420
|
},
|
|
412
421
|
},
|
|
413
422
|
{
|
|
@@ -423,7 +432,7 @@ Actions: create (title/description/price) | mine | update (product_id + changed
|
|
|
423
432
|
inputSchema: {
|
|
424
433
|
type: 'object',
|
|
425
434
|
properties: {
|
|
426
|
-
api_key: { type: 'string', description: "Seller's api_key" },
|
|
435
|
+
api_key: { type: 'string', description: "Seller's api_key (or omit and set the WEBAZ_API_KEY env var)" },
|
|
427
436
|
action: {
|
|
428
437
|
type: 'string',
|
|
429
438
|
enum: ['create', 'mine', 'update', 'delist', 'relist', 'trash', 'delete'],
|
|
@@ -479,7 +488,7 @@ Actions: create (title/description/price) | mine | update (product_id + changed
|
|
|
479
488
|
description: '[S4] Product-origin claims (challengeable). E.g. {"made_in":"Kyoto JP","material":"100% cotton GOTS-cert","certs":[{"name":"GOTS","sha256":"<64-hex>"}]}. Total JSON ≤4KB; any cert sha256 must be 64-hex. Any buyer can challenge.',
|
|
480
489
|
},
|
|
481
490
|
},
|
|
482
|
-
required: [
|
|
491
|
+
required: [],
|
|
483
492
|
},
|
|
484
493
|
},
|
|
485
494
|
{
|
|
@@ -501,7 +510,7 @@ Options:
|
|
|
501
510
|
inputSchema: {
|
|
502
511
|
type: 'object',
|
|
503
512
|
properties: {
|
|
504
|
-
api_key: { type: 'string', description: "Buyer's api_key" },
|
|
513
|
+
api_key: { type: 'string', description: "Buyer's api_key (or omit and set the WEBAZ_API_KEY env var)" },
|
|
505
514
|
product_id: { type: 'string', description: 'Product ID to buy (from webaz_search)' },
|
|
506
515
|
quantity: { type: 'number', description: 'Quantity, default 1' },
|
|
507
516
|
shipping_address: { type: 'string', description: 'Shipping address' },
|
|
@@ -526,7 +535,7 @@ Options:
|
|
|
526
535
|
description: '[B5] Per-order donation pct (0 / 0.5 / 1 / 2 / 5). Computed separately + into charity_fund, posted on order complete.',
|
|
527
536
|
},
|
|
528
537
|
},
|
|
529
|
-
required: ['
|
|
538
|
+
required: ['product_id', 'shipping_address'],
|
|
530
539
|
},
|
|
531
540
|
},
|
|
532
541
|
{
|
|
@@ -534,15 +543,15 @@ Options:
|
|
|
534
543
|
// was ~927 chars, now ~430 chars
|
|
535
544
|
description: `STATUS TRANSITIONS on an order — NOT for editing order content (price/qty/address immutable after creation). Each role can only perform their own actions.
|
|
536
545
|
|
|
537
|
-
- **Seller**: accept (24h after payment) | ship (needs tracking, within handling time)
|
|
538
|
-
- **Logistics**: pickup (48h after ship) | transit | deliver (needs proof description)
|
|
546
|
+
- **Seller**: accept (24h after payment) | ship (needs tracking/notes, within handling time) | pickup/transit/deliver ONLY when order.logistics_id is empty (Phase-1 self-fulfill; seller carries logistics responsibility) | decline (actively refuse a PAID order instead of silent timeout; requires decline_reason_code — objective codes [stock_consumed_concurrent/stale_price_snapshot/force_majeure] go to a PROVISIONAL fault you must then contest within the window, NOT auto-cleared; subjective codes [price_regret/cherry_pick/other] settle immediately as seller-fault + buyer refund) | contest_decline (open human arbitration on an objective-claimed provisional fault, within the contest window, to be cleared to no-fault; pass evidence_description — window expiry finalizes as fault)
|
|
547
|
+
- **Logistics**: pickup (48h after ship) | transit | deliver (needs proof description) when assigned or claiming an unassigned shipped order
|
|
539
548
|
- **Buyer**: confirm (→ fund settlement) | dispute (needs reason; freezes funds → arbitration)
|
|
540
549
|
|
|
541
550
|
Missing deadline → protocol auto-marks party in default.`,
|
|
542
551
|
inputSchema: {
|
|
543
552
|
type: 'object',
|
|
544
553
|
properties: {
|
|
545
|
-
api_key: { type: 'string', description: "Operator's api_key" },
|
|
554
|
+
api_key: { type: 'string', description: "Operator's api_key (or omit and set the WEBAZ_API_KEY env var)" },
|
|
546
555
|
order_id: { type: 'string', description: 'Order ID' },
|
|
547
556
|
action: {
|
|
548
557
|
type: 'string',
|
|
@@ -560,7 +569,7 @@ Missing deadline → protocol auto-marks party in default.`,
|
|
|
560
569
|
description: 'Evidence description (recommended for ship/pickup/deliver; required for dispute)',
|
|
561
570
|
},
|
|
562
571
|
},
|
|
563
|
-
required: ['
|
|
572
|
+
required: ['order_id', 'action'],
|
|
564
573
|
},
|
|
565
574
|
},
|
|
566
575
|
{
|
|
@@ -570,10 +579,10 @@ Missing deadline → protocol auto-marks party in default.`,
|
|
|
570
579
|
inputSchema: {
|
|
571
580
|
type: 'object',
|
|
572
581
|
properties: {
|
|
573
|
-
api_key: { type: 'string', description: "Querier's api_key" },
|
|
582
|
+
api_key: { type: 'string', description: "Querier's api_key (or omit and set the WEBAZ_API_KEY env var)" },
|
|
574
583
|
order_id: { type: 'string', description: 'Order ID' },
|
|
575
584
|
},
|
|
576
|
-
required: ['
|
|
585
|
+
required: ['order_id'],
|
|
577
586
|
},
|
|
578
587
|
},
|
|
579
588
|
{
|
|
@@ -591,14 +600,14 @@ Actions:
|
|
|
591
600
|
inputSchema: {
|
|
592
601
|
type: 'object',
|
|
593
602
|
properties: {
|
|
594
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
603
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
595
604
|
action: {
|
|
596
605
|
type: 'string',
|
|
597
606
|
enum: ['view', 'deposits', 'withdrawals', 'income'],
|
|
598
607
|
description: 'Action type (default: view)',
|
|
599
608
|
},
|
|
600
609
|
},
|
|
601
|
-
required: [
|
|
610
|
+
required: [],
|
|
602
611
|
},
|
|
603
612
|
},
|
|
604
613
|
{
|
|
@@ -610,11 +619,11 @@ Actions:
|
|
|
610
619
|
inputSchema: {
|
|
611
620
|
type: 'object',
|
|
612
621
|
properties: {
|
|
613
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
622
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
614
623
|
unread: { type: 'boolean', description: 'Return only unread (default false)' },
|
|
615
624
|
mark_read: { type: 'boolean', description: 'Auto-mark read after call (default false)' },
|
|
616
625
|
},
|
|
617
|
-
required: [
|
|
626
|
+
required: [],
|
|
618
627
|
},
|
|
619
628
|
},
|
|
620
629
|
{
|
|
@@ -637,7 +646,7 @@ Protocol auto-judges (no human): respondent silent 48h → favor initiator; arbi
|
|
|
637
646
|
inputSchema: {
|
|
638
647
|
type: 'object',
|
|
639
648
|
properties: {
|
|
640
|
-
api_key: { type: 'string', description: "Operator's api_key" },
|
|
649
|
+
api_key: { type: 'string', description: "Operator's api_key (or omit and set the WEBAZ_API_KEY env var)" },
|
|
641
650
|
action: {
|
|
642
651
|
type: 'string',
|
|
643
652
|
enum: ['view', 'list_open', 'respond', 'add_evidence', 'arbitrate'],
|
|
@@ -668,7 +677,7 @@ Protocol auto-judges (no human): respondent silent 48h → favor initiator; arbi
|
|
|
668
677
|
},
|
|
669
678
|
ruling_reason: { type: 'string', description: 'Ruling reason (required for arbitrate; permanently recorded on-chain)' },
|
|
670
679
|
},
|
|
671
|
-
required: ['
|
|
680
|
+
required: ['action'],
|
|
672
681
|
},
|
|
673
682
|
},
|
|
674
683
|
{
|
|
@@ -695,7 +704,7 @@ Actions:
|
|
|
695
704
|
inputSchema: {
|
|
696
705
|
type: 'object',
|
|
697
706
|
properties: {
|
|
698
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
707
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
699
708
|
action: {
|
|
700
709
|
type: 'string',
|
|
701
710
|
enum: ['create', 'view', 'mine', 'submit_seller_evidence', 'available', 'vote', 'eligibility', 'verifier_status', 'apply', 'withdraw_application', 'appeal'],
|
|
@@ -718,7 +727,7 @@ Actions:
|
|
|
718
727
|
// appeal
|
|
719
728
|
reason: { type: 'string', description: 'Appeal reason (required for appeal, ≤500 chars)' },
|
|
720
729
|
},
|
|
721
|
-
required: ['
|
|
730
|
+
required: ['action'],
|
|
722
731
|
},
|
|
723
732
|
},
|
|
724
733
|
{
|
|
@@ -743,7 +752,7 @@ Actions: list (no auth) | publish (seller) | subscribe / unsubscribe (buyer) | m
|
|
|
743
752
|
inputSchema: {
|
|
744
753
|
type: 'object',
|
|
745
754
|
properties: {
|
|
746
|
-
api_key: { type: 'string', description: 'Your api_key (omit for list)' },
|
|
755
|
+
api_key: { type: 'string', description: 'Your api_key (omit for list) (or set the WEBAZ_API_KEY env var)' },
|
|
747
756
|
action: {
|
|
748
757
|
type: 'string',
|
|
749
758
|
enum: ['list', 'publish', 'subscribe', 'unsubscribe', 'my_skills', 'my_subs'],
|
|
@@ -807,7 +816,7 @@ Public-profile actions:
|
|
|
807
816
|
inputSchema: {
|
|
808
817
|
type: 'object',
|
|
809
818
|
properties: {
|
|
810
|
-
api_key: { type: 'string', description: 'Your api_key (required for view/add_role/switch_role/view_user; optional for public feed)' },
|
|
819
|
+
api_key: { type: 'string', description: 'Your api_key (required for view/add_role/switch_role/view_user; optional for public feed) (or set the WEBAZ_API_KEY env var)' },
|
|
811
820
|
action: {
|
|
812
821
|
type: 'string',
|
|
813
822
|
enum: ['view', 'add_role', 'switch_role', 'view_user', 'feed'],
|
|
@@ -841,10 +850,10 @@ Use revoke when: PERMANENT decommission of agent/device, OR want access death NO
|
|
|
841
850
|
inputSchema: {
|
|
842
851
|
type: 'object',
|
|
843
852
|
properties: {
|
|
844
|
-
api_key: { type: 'string', description: 'Your current api_key (the one to revoke)' },
|
|
853
|
+
api_key: { type: 'string', description: 'Your current api_key (the one to revoke) (or set the WEBAZ_API_KEY env var)' },
|
|
845
854
|
reason: { type: 'string', description: 'Optional: leaked / lost_device / rotation / unspecified' },
|
|
846
855
|
},
|
|
847
|
-
required: [
|
|
856
|
+
required: [],
|
|
848
857
|
},
|
|
849
858
|
},
|
|
850
859
|
{
|
|
@@ -856,10 +865,10 @@ Safer than \`webaz_revoke_key\` — atomic swap, no access gap.`,
|
|
|
856
865
|
inputSchema: {
|
|
857
866
|
type: 'object',
|
|
858
867
|
properties: {
|
|
859
|
-
api_key: { type: 'string', description: 'Your current api_key (will be invalidated after PWA confirm)' },
|
|
868
|
+
api_key: { type: 'string', description: 'Your current api_key (will be invalidated after PWA confirm) (or set the WEBAZ_API_KEY env var)' },
|
|
860
869
|
reason: { type: 'string', description: 'Optional: rotation / leaked / scheduled' },
|
|
861
870
|
},
|
|
862
|
-
required: [
|
|
871
|
+
required: [],
|
|
863
872
|
},
|
|
864
873
|
},
|
|
865
874
|
{
|
|
@@ -872,9 +881,9 @@ Safer than \`webaz_revoke_key\` — atomic swap, no access gap.`,
|
|
|
872
881
|
inputSchema: {
|
|
873
882
|
type: 'object',
|
|
874
883
|
properties: {
|
|
875
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
884
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
876
885
|
},
|
|
877
|
-
required: [
|
|
886
|
+
required: [],
|
|
878
887
|
},
|
|
879
888
|
},
|
|
880
889
|
{
|
|
@@ -887,15 +896,15 @@ Safer than \`webaz_revoke_key\` — atomic swap, no access gap.`,
|
|
|
887
896
|
inputSchema: {
|
|
888
897
|
type: 'object',
|
|
889
898
|
properties: {
|
|
890
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
899
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
891
900
|
product_id: { type: 'string', description: 'Product to promote (from webaz_search)' },
|
|
892
901
|
side: {
|
|
893
902
|
type: 'string',
|
|
894
|
-
enum: ['
|
|
895
|
-
description: '
|
|
903
|
+
enum: ['auto'],
|
|
904
|
+
description: 'Deprecated / no-op — placement is always automatic (system-decided). Left/right选择已下线。',
|
|
896
905
|
},
|
|
897
906
|
},
|
|
898
|
-
required: ['
|
|
907
|
+
required: ['product_id'],
|
|
899
908
|
},
|
|
900
909
|
},
|
|
901
910
|
{
|
|
@@ -909,12 +918,12 @@ Actions: list | block | unblock.`,
|
|
|
909
918
|
inputSchema: {
|
|
910
919
|
type: 'object',
|
|
911
920
|
properties: {
|
|
912
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
921
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
913
922
|
action: { type: 'string', enum: ['list', 'block', 'unblock'], description: 'list: my blocked users | block: add | unblock: remove' },
|
|
914
923
|
user_id: { type: 'string', description: 'Target user id (required for block/unblock)' },
|
|
915
924
|
reason: { type: 'string', description: 'Optional reason for block (e.g. "fake product", "abuse")' },
|
|
916
925
|
},
|
|
917
|
-
required: ['
|
|
926
|
+
required: ['action'],
|
|
918
927
|
},
|
|
919
928
|
},
|
|
920
929
|
{
|
|
@@ -923,11 +932,11 @@ Actions: list | block | unblock.`,
|
|
|
923
932
|
inputSchema: {
|
|
924
933
|
type: 'object',
|
|
925
934
|
properties: {
|
|
926
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
935
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
927
936
|
action: { type: 'string', enum: ['list', 'follow', 'unfollow', 'status'], description: 'list: my follows + followers | follow/unfollow: change relation | status: check if I follow a user' },
|
|
928
937
|
user_id: { type: 'string', description: 'Target user (required for follow/unfollow/status)' },
|
|
929
938
|
},
|
|
930
|
-
required: ['
|
|
939
|
+
required: ['action'],
|
|
931
940
|
},
|
|
932
941
|
},
|
|
933
942
|
{
|
|
@@ -941,12 +950,12 @@ USE THIS for "what's popular near me / 我附近 / 同城" — geo-aggregated, n
|
|
|
941
950
|
inputSchema: {
|
|
942
951
|
type: 'object',
|
|
943
952
|
properties: {
|
|
944
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
953
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
945
954
|
action: { type: 'string', enum: ['query', 'set_location', 'clear_location'], description: 'query: get aggregated nearby activity | set_location: set your geo cell | clear_location: remove' },
|
|
946
955
|
lat: { type: 'number', description: 'Latitude -90..90 (for set_location, auto-truncated to 0.1°)' },
|
|
947
956
|
lng: { type: 'number', description: 'Longitude -180..180 (for set_location, auto-truncated to 0.1°)' },
|
|
948
957
|
},
|
|
949
|
-
required: ['
|
|
958
|
+
required: ['action'],
|
|
950
959
|
},
|
|
951
960
|
},
|
|
952
961
|
{
|
|
@@ -958,12 +967,12 @@ USE THIS for "what's popular near me / 我附近 / 同城" — geo-aggregated, n
|
|
|
958
967
|
inputSchema: {
|
|
959
968
|
type: 'object',
|
|
960
969
|
properties: {
|
|
961
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
970
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
962
971
|
action: { type: 'string', enum: ['read', 'set'], description: 'read: get current default | set: update' },
|
|
963
972
|
text: { type: 'string', description: 'Full address as free-text string (e.g. "John Doe / 1 Test St / Singapore SG / +65 12345678"). Required for set. ≤ 200 chars.' },
|
|
964
973
|
region: { type: 'string', description: 'Region tag for shipping match (e.g. "global", "china", "SG"). Optional for set. ≤ 40 chars.' },
|
|
965
974
|
},
|
|
966
|
-
required: ['
|
|
975
|
+
required: ['action'],
|
|
967
976
|
},
|
|
968
977
|
},
|
|
969
978
|
{
|
|
@@ -979,7 +988,7 @@ Actions: list_mine | add (external_url + product/anchor) | delete | by_product |
|
|
|
979
988
|
inputSchema: {
|
|
980
989
|
type: 'object',
|
|
981
990
|
properties: {
|
|
982
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
991
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
983
992
|
action: { type: 'string', enum: ['list_mine', 'add', 'delete', 'by_product', 'by_anchor'], description: 'list_mine | add (need external_url + product/anchor) | delete | by_product | by_anchor' },
|
|
984
993
|
external_url: { type: 'string', description: 'For action=add' },
|
|
985
994
|
title: { type: 'string', description: 'For action=add (optional)' },
|
|
@@ -988,7 +997,7 @@ Actions: list_mine | add (external_url + product/anchor) | delete | by_product |
|
|
|
988
997
|
related_anchor: { type: 'string', description: 'For action=add or by_anchor' },
|
|
989
998
|
shareable_id: { type: 'string', description: 'For action=delete' },
|
|
990
999
|
},
|
|
991
|
-
required: ['
|
|
1000
|
+
required: ['action'],
|
|
992
1001
|
},
|
|
993
1002
|
},
|
|
994
1003
|
// ── P3 RFQ / bid / chat / auto_bid(MCP 通过 HTTP 调 PWA,复用所有校验+状态机)────
|
|
@@ -1017,7 +1026,7 @@ Shipping address falls back to webaz_default_address if omitted.`,
|
|
|
1017
1026
|
inputSchema: {
|
|
1018
1027
|
type: 'object',
|
|
1019
1028
|
properties: {
|
|
1020
|
-
api_key: { type: 'string', description: 'Your api_key' },
|
|
1029
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1021
1030
|
action: { type: 'string', enum: ['create', 'mine', 'browse', 'detail', 'award', 'cancel'] },
|
|
1022
1031
|
// create
|
|
1023
1032
|
title: { type: 'string' },
|
|
@@ -1036,7 +1045,7 @@ Shipping address falls back to webaz_default_address if omitted.`,
|
|
|
1036
1045
|
rfq_id: { type: 'string' },
|
|
1037
1046
|
bid_id: { type: 'string', description: 'Optional for award — if omitted, auto-pick current lowest bid' },
|
|
1038
1047
|
},
|
|
1039
|
-
required: ['
|
|
1048
|
+
required: ['action'],
|
|
1040
1049
|
},
|
|
1041
1050
|
},
|
|
1042
1051
|
{
|
|
@@ -1050,7 +1059,7 @@ Actions: submit (rfq_id + price + qty_offered + fulfillment_type; optional eta/n
|
|
|
1050
1059
|
inputSchema: {
|
|
1051
1060
|
type: 'object',
|
|
1052
1061
|
properties: {
|
|
1053
|
-
api_key: { type: 'string', description: 'Seller api_key' },
|
|
1062
|
+
api_key: { type: 'string', description: 'Seller api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1054
1063
|
action: { type: 'string', enum: ['submit', 'patch', 'cancel', 'list_mine'] },
|
|
1055
1064
|
rfq_id: { type: 'string' },
|
|
1056
1065
|
bid_id: { type: 'string' },
|
|
@@ -1061,7 +1070,7 @@ Actions: submit (rfq_id + price + qty_offered + fulfillment_type; optional eta/n
|
|
|
1061
1070
|
note: { type: 'string' },
|
|
1062
1071
|
offer_id: { type: 'string', description: 'Optional; reference existing offer' },
|
|
1063
1072
|
},
|
|
1064
|
-
required: ['
|
|
1073
|
+
required: ['action'],
|
|
1065
1074
|
},
|
|
1066
1075
|
},
|
|
1067
1076
|
{
|
|
@@ -1081,7 +1090,7 @@ webaz_blocklist hides from search but does NOT auto-silence existing convs (busi
|
|
|
1081
1090
|
inputSchema: {
|
|
1082
1091
|
type: 'object',
|
|
1083
1092
|
properties: {
|
|
1084
|
-
api_key: { type: 'string' },
|
|
1093
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1085
1094
|
action: { type: 'string', enum: ['start', 'list', 'read', 'send', 'mark_read', 'block'] },
|
|
1086
1095
|
kind: { type: 'string', enum: ['order', 'rfq', 'listing_qa'] },
|
|
1087
1096
|
context_id: { type: 'string' },
|
|
@@ -1089,7 +1098,7 @@ webaz_blocklist hides from search but does NOT auto-silence existing convs (busi
|
|
|
1089
1098
|
conversation_id: { type: 'string' },
|
|
1090
1099
|
body: { type: 'string', description: 'Message body for send action (≤2000 chars)' },
|
|
1091
1100
|
},
|
|
1092
|
-
required: ['
|
|
1101
|
+
required: ['action'],
|
|
1093
1102
|
},
|
|
1094
1103
|
},
|
|
1095
1104
|
{
|
|
@@ -1129,7 +1138,7 @@ Actions (15):
|
|
|
1129
1138
|
inputSchema: {
|
|
1130
1139
|
type: 'object',
|
|
1131
1140
|
properties: {
|
|
1132
|
-
api_key: { type: 'string' },
|
|
1141
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1133
1142
|
action: { type: 'string', enum: ['list', 'detail', 'create', 'claim', 'proof', 'confirm', 'disclose', 'cancel', 'me', 'stories', 'leaderboard', 'repay', 'repay_respond', 'donate', 'fund'] },
|
|
1134
1143
|
wish_id: { type: 'string' },
|
|
1135
1144
|
fulfillment_id: { type: 'string' },
|
|
@@ -1165,7 +1174,7 @@ Actions: create (seller, needs title/price/stock + content_hash sha256 + content
|
|
|
1165
1174
|
inputSchema: {
|
|
1166
1175
|
type: 'object',
|
|
1167
1176
|
properties: {
|
|
1168
|
-
api_key: { type: 'string' },
|
|
1177
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1169
1178
|
action: { type: 'string', enum: ['create', 'list', 'detail', 'patch'] },
|
|
1170
1179
|
product_id: { type: 'string' },
|
|
1171
1180
|
title: { type: 'string' }, price: { type: 'number' }, stock: { type: 'number' },
|
|
@@ -1190,11 +1199,11 @@ Actions: toggle (same endpoint; 2nd call auto-unlikes) | status (my like status
|
|
|
1190
1199
|
inputSchema: {
|
|
1191
1200
|
type: 'object',
|
|
1192
1201
|
properties: {
|
|
1193
|
-
api_key: { type: 'string' },
|
|
1202
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1194
1203
|
action: { type: 'string', enum: ['toggle', 'status'] },
|
|
1195
1204
|
shareable_id: { type: 'string' },
|
|
1196
1205
|
},
|
|
1197
|
-
required: ['
|
|
1206
|
+
required: ['action', 'shareable_id'],
|
|
1198
1207
|
},
|
|
1199
1208
|
},
|
|
1200
1209
|
{
|
|
@@ -1239,7 +1248,7 @@ Actions:
|
|
|
1239
1248
|
inputSchema: {
|
|
1240
1249
|
type: 'object',
|
|
1241
1250
|
properties: {
|
|
1242
|
-
api_key: { type: 'string' },
|
|
1251
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1243
1252
|
action: { type: 'string', enum: ['create', 'browse', 'mine', 'detail', 'bid', 'cancel'] },
|
|
1244
1253
|
title: { type: 'string' },
|
|
1245
1254
|
qty: { type: 'number' },
|
|
@@ -1253,7 +1262,7 @@ Actions:
|
|
|
1253
1262
|
auction_id: { type: 'string' },
|
|
1254
1263
|
price: { type: 'number' },
|
|
1255
1264
|
},
|
|
1256
|
-
required: ['
|
|
1265
|
+
required: ['action'],
|
|
1257
1266
|
},
|
|
1258
1267
|
},
|
|
1259
1268
|
{
|
|
@@ -1267,7 +1276,7 @@ Actions: get | set (categories[] / regions[] / max_eta_h / bid_strategy) | disab
|
|
|
1267
1276
|
inputSchema: {
|
|
1268
1277
|
type: 'object',
|
|
1269
1278
|
properties: {
|
|
1270
|
-
api_key: { type: 'string' },
|
|
1279
|
+
api_key: { type: 'string', description: 'Your api_key (or set the WEBAZ_API_KEY env var)' },
|
|
1271
1280
|
action: { type: 'string', enum: ['get', 'set', 'disable'] },
|
|
1272
1281
|
categories: { type: 'array', items: { type: 'string' } },
|
|
1273
1282
|
regions: { type: 'array', items: { type: 'string' } },
|
|
@@ -1280,7 +1289,7 @@ Actions: get | set (categories[] / regions[] / max_eta_h / bid_strategy) | disab
|
|
|
1280
1289
|
cooldown_min: { type: 'number' },
|
|
1281
1290
|
enabled: { type: 'boolean' },
|
|
1282
1291
|
},
|
|
1283
|
-
required: ['
|
|
1292
|
+
required: ['action'],
|
|
1284
1293
|
},
|
|
1285
1294
|
},
|
|
1286
1295
|
{
|
|
@@ -1300,7 +1309,7 @@ Actions: list (no auth, filters: kind/billing/query) | detail (public, no conten
|
|
|
1300
1309
|
inputSchema: {
|
|
1301
1310
|
type: 'object',
|
|
1302
1311
|
properties: {
|
|
1303
|
-
api_key: { type: 'string', description: 'Your api_key (omit for list/detail)' },
|
|
1312
|
+
api_key: { type: 'string', description: 'Your api_key (omit for list/detail) (or set the WEBAZ_API_KEY env var)' },
|
|
1304
1313
|
action: {
|
|
1305
1314
|
type: 'string',
|
|
1306
1315
|
enum: ['list', 'detail', 'publish', 'update', 'delist', 'resubmit', 'purchase', 'read', 'my_skills', 'library'],
|
|
@@ -1337,7 +1346,7 @@ Enums: **category** phone/computer/appliance/furniture/clothing/book/toy/sports/
|
|
|
1337
1346
|
inputSchema: {
|
|
1338
1347
|
type: 'object',
|
|
1339
1348
|
properties: {
|
|
1340
|
-
api_key: { type: 'string', description: 'Your api_key (omit for browse/detail)' },
|
|
1349
|
+
api_key: { type: 'string', description: 'Your api_key (omit for browse/detail) (or set the WEBAZ_API_KEY env var)' },
|
|
1341
1350
|
action: { type: 'string', enum: ['browse', 'detail', 'publish', 'update', 'mine', 'buy'], description: 'Action to execute' },
|
|
1342
1351
|
item_id: { type: 'string', description: 'Item ID (required for detail/update/buy)' },
|
|
1343
1352
|
// publish / update
|
|
@@ -1386,7 +1395,7 @@ Seller actions:
|
|
|
1386
1395
|
inputSchema: {
|
|
1387
1396
|
type: 'object',
|
|
1388
1397
|
properties: {
|
|
1389
|
-
api_key: { type: 'string', description: 'Your api_key (omit for get_campaign)' },
|
|
1398
|
+
api_key: { type: 'string', description: 'Your api_key (omit for get_campaign) (or set the WEBAZ_API_KEY env var)' },
|
|
1390
1399
|
action: { type: 'string', enum: ['get_campaign', 'apply', 'link_note', 'my_claims', 'create_campaign', 'cancel_campaign', 'my_campaigns', 'campaign_claims'], description: 'Action to execute' },
|
|
1391
1400
|
product_id: { type: 'string', description: 'Product ID (required for get_campaign/apply/create_campaign/cancel_campaign)' },
|
|
1392
1401
|
claim_id: { type: 'string', description: 'Claim ID (required for link_note)' },
|
|
@@ -1415,7 +1424,7 @@ Gate by type: ux_issue/bug (reporting = using) → login only, NO Passkey, anyon
|
|
|
1415
1424
|
type: 'object',
|
|
1416
1425
|
properties: {
|
|
1417
1426
|
action: { type: 'string', enum: ['submit', 'my', 'get'], description: 'submit (default) | my | get' },
|
|
1418
|
-
api_key: { type: 'string', description: "User's api_key (real person required)" },
|
|
1427
|
+
api_key: { type: 'string', description: "User's api_key (real person required; or set the WEBAZ_API_KEY env var)" },
|
|
1419
1428
|
type: { type: 'string', enum: ['ux_issue', 'bug', 'proposal'], description: 'submit: kind of feedback' },
|
|
1420
1429
|
area: { type: 'string', description: 'submit: which feature, e.g. search / order / dispute' },
|
|
1421
1430
|
severity: { type: 'string', enum: ['low', 'annoying', 'blocking'], description: 'submit: for ux_issue/bug' },
|
|
@@ -1423,7 +1432,7 @@ Gate by type: ux_issue/bug (reporting = using) → login only, NO Passkey, anyon
|
|
|
1423
1432
|
text: { type: 'string', description: 'submit: the feedback / idea (≥5 chars)' },
|
|
1424
1433
|
feedback_id: { type: 'string', description: 'get: the feedback id' },
|
|
1425
1434
|
},
|
|
1426
|
-
required: [
|
|
1435
|
+
required: [],
|
|
1427
1436
|
},
|
|
1428
1437
|
},
|
|
1429
1438
|
{
|
|
@@ -1446,7 +1455,7 @@ Coordinates + records only — NO merge/reward; acceptance (done) = human mainta
|
|
|
1446
1455
|
type: 'object',
|
|
1447
1456
|
properties: {
|
|
1448
1457
|
action: { type: 'string', enum: ['list_open', 'detail', 'suggest', 'claim', 'submit', 'status', 'profile'], description: 'list_open (default) | detail | suggest | claim | submit | status | profile' },
|
|
1449
|
-
api_key: { type: 'string', description: 'claim/submit/status/profile: your api_key (accountable identity). NOT needed for list_open/detail/suggest.' },
|
|
1458
|
+
api_key: { type: 'string', description: 'claim/submit/status/profile: your api_key (accountable identity). NOT needed for list_open/detail/suggest. (or set the WEBAZ_API_KEY env var)' },
|
|
1450
1459
|
task_id: { type: 'string', description: 'detail / claim / submit: the task id' },
|
|
1451
1460
|
area: { type: 'string', description: 'list_open: area filter / suggest: suggested area (e.g. search / docs / mcp)' },
|
|
1452
1461
|
risk_level: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], description: 'list_open: optional risk filter' },
|
|
@@ -1473,7 +1482,7 @@ Coordinates + records only — NO merge/reward; acceptance (done) = human mainta
|
|
|
1473
1482
|
// RFC-004: webaz_feedback — agent-native "use → build" 反馈(双模;仅 NETWORK 能送达)
|
|
1474
1483
|
async function handleFeedback(args) {
|
|
1475
1484
|
const action = args.action || 'submit';
|
|
1476
|
-
const apiKey = args
|
|
1485
|
+
const apiKey = resolveMcpApiKey(args);
|
|
1477
1486
|
if (!apiKey)
|
|
1478
1487
|
return { error: 'api_key required' };
|
|
1479
1488
|
if (toolBackend('webaz_feedback') !== 'network') {
|
|
@@ -1531,7 +1540,7 @@ function buildContributeHandoff(cct, taskId) {
|
|
|
1531
1540
|
// 端口 #329/#331);claim/submit/status/profile 需 key(真实可问责身份,走受 #330 守卫的 member 端口)。
|
|
1532
1541
|
export async function handleContribute(args) {
|
|
1533
1542
|
const action = args.action || 'list_open';
|
|
1534
|
-
const apiKey = args
|
|
1543
|
+
const apiKey = resolveMcpApiKey(args);
|
|
1535
1544
|
if (toolBackend('webaz_contribute') !== 'network') {
|
|
1536
1545
|
return {
|
|
1537
1546
|
_mode: 'sandbox',
|
|
@@ -2138,11 +2147,11 @@ async function handleVerifyPrice(args) {
|
|
|
2138
2147
|
if (toolBackend('webaz_verify_price') === 'network') {
|
|
2139
2148
|
return apiCall('/api/verify-price', {
|
|
2140
2149
|
method: 'POST',
|
|
2141
|
-
apiKey: args
|
|
2150
|
+
apiKey: resolveMcpApiKey(args),
|
|
2142
2151
|
body: { product_id: args.product_id, quantity: Number(args.quantity ?? 1) },
|
|
2143
2152
|
});
|
|
2144
2153
|
}
|
|
2145
|
-
const auth = requireAuth(db, args
|
|
2154
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
2146
2155
|
if ('error' in auth)
|
|
2147
2156
|
return auth;
|
|
2148
2157
|
const { user } = auth;
|
|
@@ -2188,7 +2197,7 @@ async function handleVerifyPrice(args) {
|
|
|
2188
2197
|
async function handleListProduct(args) {
|
|
2189
2198
|
// Wave 3 audit P0: 加 action 分发 — agent 卖家能完整管理目录(不止 create)
|
|
2190
2199
|
const action = args.action || 'create';
|
|
2191
|
-
const apiKey = args
|
|
2200
|
+
const apiKey = resolveMcpApiKey(args);
|
|
2192
2201
|
if (!apiKey)
|
|
2193
2202
|
return { error: 'api_key required' };
|
|
2194
2203
|
// RFC-003 P2b: NETWORK 模式 — 卖家目录管理全部转发生产端点(单一真相源)
|
|
@@ -2366,9 +2375,9 @@ async function handlePlaceOrder(args) {
|
|
|
2366
2375
|
body.shipping_address = args.shipping_address;
|
|
2367
2376
|
if (args.donation_pct != null)
|
|
2368
2377
|
body.donation_pct = args.donation_pct;
|
|
2369
|
-
return apiCall('/api/orders', { method: 'POST', apiKey: args
|
|
2378
|
+
return apiCall('/api/orders', { method: 'POST', apiKey: resolveMcpApiKey(args), body });
|
|
2370
2379
|
}
|
|
2371
|
-
const auth = requireAuth(db, args
|
|
2380
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
2372
2381
|
if ('error' in auth)
|
|
2373
2382
|
return auth;
|
|
2374
2383
|
const { user } = auth;
|
|
@@ -2535,7 +2544,7 @@ async function handleUpdateOrder(args) {
|
|
|
2535
2544
|
return { error: 'order_id and action required' };
|
|
2536
2545
|
return apiCall(`/api/orders/${encodeURIComponent(orderId)}/action`, {
|
|
2537
2546
|
method: 'POST',
|
|
2538
|
-
apiKey: args
|
|
2547
|
+
apiKey: resolveMcpApiKey(args),
|
|
2539
2548
|
body: {
|
|
2540
2549
|
action,
|
|
2541
2550
|
notes: args.notes ?? '',
|
|
@@ -2545,7 +2554,7 @@ async function handleUpdateOrder(args) {
|
|
|
2545
2554
|
},
|
|
2546
2555
|
});
|
|
2547
2556
|
}
|
|
2548
|
-
const auth = requireAuth(db, args
|
|
2557
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
2549
2558
|
if ('error' in auth)
|
|
2550
2559
|
return auth;
|
|
2551
2560
|
const { user } = auth;
|
|
@@ -2559,7 +2568,7 @@ async function handleUpdateOrder(args) {
|
|
|
2559
2568
|
// agent-native 协议要求"哪个接口进结果一致"。MCP confirm 不再自己结算,
|
|
2560
2569
|
// 走 PWA /api/orders/:id/action 的 settleOrder + settleCommission(authoritative)。
|
|
2561
2570
|
if (action === 'confirm') {
|
|
2562
|
-
const apiKey = args
|
|
2571
|
+
const apiKey = resolveMcpApiKey(args);
|
|
2563
2572
|
const result = await pwaApi('POST', `/orders/${encodeURIComponent(orderId)}/action`, apiKey, {
|
|
2564
2573
|
action: 'confirm',
|
|
2565
2574
|
notes,
|
|
@@ -2668,9 +2677,9 @@ async function handleGetStatus(args) {
|
|
|
2668
2677
|
const orderId = args.order_id;
|
|
2669
2678
|
if (!orderId)
|
|
2670
2679
|
return { error: 'order_id required' };
|
|
2671
|
-
return apiCall(`/api/orders/${encodeURIComponent(orderId)}`, { apiKey: args
|
|
2680
|
+
return apiCall(`/api/orders/${encodeURIComponent(orderId)}`, { apiKey: resolveMcpApiKey(args) });
|
|
2672
2681
|
}
|
|
2673
|
-
const auth = requireAuth(db, args
|
|
2682
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
2674
2683
|
if ('error' in auth)
|
|
2675
2684
|
return auth;
|
|
2676
2685
|
const statusInfo = getOrderStatus(db, args.order_id);
|
|
@@ -2707,7 +2716,7 @@ async function handleGetStatus(args) {
|
|
|
2707
2716
|
async function handleWallet(args) {
|
|
2708
2717
|
// Wave 3 audit P0: 加 action 分发 — agent 能查充值/提现/收入历史(写操作仍 UI-only 走 2FA)
|
|
2709
2718
|
const action = args.action || 'view';
|
|
2710
|
-
const apiKey = args
|
|
2719
|
+
const apiKey = resolveMcpApiKey(args);
|
|
2711
2720
|
if (!apiKey)
|
|
2712
2721
|
return { error: 'api_key required' };
|
|
2713
2722
|
// RFC-003 Batch 4:NETWORK 模式 → webaz.xyz 真网络【只读】(Bearer api_key)。
|
|
@@ -2775,14 +2784,14 @@ async function handleWallet(args) {
|
|
|
2775
2784
|
async function handleNotifications(args) {
|
|
2776
2785
|
// RFC-003 Batch 1:NETWORK 模式 → 调 webaz.xyz 真网络通知端点(Bearer api_key);SANDBOX 走本地。
|
|
2777
2786
|
if (toolBackend('webaz_notifications') === 'network') {
|
|
2778
|
-
const apiKey =
|
|
2787
|
+
const apiKey = resolveMcpApiKey(args);
|
|
2779
2788
|
if (!apiKey)
|
|
2780
2789
|
return { error: 'api_key required' };
|
|
2781
2790
|
if (args.mark_read)
|
|
2782
2791
|
await apiCall('/api/notifications/read', { method: 'POST', apiKey });
|
|
2783
2792
|
return await apiCall('/api/notifications' + (args.unread === true ? '?unread=1' : ''), { apiKey });
|
|
2784
2793
|
}
|
|
2785
|
-
const auth = requireAuth(db, args
|
|
2794
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
2786
2795
|
if ('error' in auth)
|
|
2787
2796
|
return auth;
|
|
2788
2797
|
const { user } = auth;
|
|
@@ -2806,7 +2815,7 @@ async function handleNotifications(args) {
|
|
|
2806
2815
|
}
|
|
2807
2816
|
// ─── 争议处理 ─────────────────────────────────────────────────
|
|
2808
2817
|
async function handleDispute(args) {
|
|
2809
|
-
const apiKey = args
|
|
2818
|
+
const apiKey = resolveMcpApiKey(args);
|
|
2810
2819
|
if (!apiKey)
|
|
2811
2820
|
return { error: 'api_key required' };
|
|
2812
2821
|
const action = args.action;
|
|
@@ -2969,7 +2978,7 @@ async function handleDispute(args) {
|
|
|
2969
2978
|
}
|
|
2970
2979
|
// ─── 索赔验证(claim-verification)处理 — Wave 6 新增 ────────────
|
|
2971
2980
|
async function handleClaimVerify(args) {
|
|
2972
|
-
const apiKey = args
|
|
2981
|
+
const apiKey = resolveMcpApiKey(args);
|
|
2973
2982
|
if (!apiKey)
|
|
2974
2983
|
return { error: 'api_key required' };
|
|
2975
2984
|
const action = String(args.action || '');
|
|
@@ -3057,7 +3066,7 @@ async function handleSkill(args) {
|
|
|
3057
3066
|
const action = args.action;
|
|
3058
3067
|
// RFC-003 Batch 3:NETWORK 模式 → webaz.xyz 真网络(Bearer api_key);SANDBOX 走本地引擎。
|
|
3059
3068
|
if (toolBackend('webaz_skill') === 'network') {
|
|
3060
|
-
const apiKey =
|
|
3069
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3061
3070
|
if (action === 'list') {
|
|
3062
3071
|
const qs = new URLSearchParams();
|
|
3063
3072
|
if (args.skill_type)
|
|
@@ -3094,8 +3103,8 @@ async function handleSkill(args) {
|
|
|
3094
3103
|
// ── 浏览 Skill 市场 ────────────────────────────────────────
|
|
3095
3104
|
if (action === 'list') {
|
|
3096
3105
|
let userId;
|
|
3097
|
-
if (args
|
|
3098
|
-
const a = requireAuth(db, args
|
|
3106
|
+
if (resolveMcpApiKey(args)) {
|
|
3107
|
+
const a = requireAuth(db, resolveMcpApiKey(args));
|
|
3099
3108
|
if (!('error' in a))
|
|
3100
3109
|
userId = a.user.id;
|
|
3101
3110
|
}
|
|
@@ -3112,7 +3121,7 @@ async function handleSkill(args) {
|
|
|
3112
3121
|
};
|
|
3113
3122
|
}
|
|
3114
3123
|
// 以下操作需要身份验证
|
|
3115
|
-
const auth = requireAuth(db, args
|
|
3124
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3116
3125
|
if ('error' in auth)
|
|
3117
3126
|
return auth;
|
|
3118
3127
|
const { user } = auth;
|
|
@@ -3253,7 +3262,7 @@ function handleMyKey(args) {
|
|
|
3253
3262
|
}
|
|
3254
3263
|
async function handleProfile(args) {
|
|
3255
3264
|
const action = args.action;
|
|
3256
|
-
const apiKey =
|
|
3265
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3257
3266
|
// RFC-003 Batch 1:NETWORK 模式 → 全部 action 调 webaz.xyz 真网络(Bearer api_key);SANDBOX 走本地。
|
|
3258
3267
|
if (toolBackend('webaz_profile') === 'network') {
|
|
3259
3268
|
if (action === 'view_user') {
|
|
@@ -3350,7 +3359,7 @@ async function handleProfile(args) {
|
|
|
3350
3359
|
function handleRevokeKey(args) {
|
|
3351
3360
|
// RFC-003 Batch 5:NETWORK 模式 → 不本地校验 key(PWA 会鉴权),直接返回 Passkey 撤销指引。
|
|
3352
3361
|
if (toolBackend('webaz_revoke_key') === 'network') {
|
|
3353
|
-
const apiKey =
|
|
3362
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3354
3363
|
const reason = (args.reason || 'unspecified').trim().slice(0, 100);
|
|
3355
3364
|
return {
|
|
3356
3365
|
_mode: 'network',
|
|
@@ -3368,7 +3377,7 @@ function handleRevokeKey(args) {
|
|
|
3368
3377
|
},
|
|
3369
3378
|
};
|
|
3370
3379
|
}
|
|
3371
|
-
const auth = requireAuth(db, args
|
|
3380
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3372
3381
|
if ('error' in auth)
|
|
3373
3382
|
return auth;
|
|
3374
3383
|
const { user } = auth;
|
|
@@ -3392,7 +3401,7 @@ function handleRevokeKey(args) {
|
|
|
3392
3401
|
function handleRotateKey(args) {
|
|
3393
3402
|
// RFC-003 Batch 5:NETWORK 模式 → 不本地校验 key(PWA 会鉴权),直接返回 Passkey 轮换指引。
|
|
3394
3403
|
if (toolBackend('webaz_rotate_key') === 'network') {
|
|
3395
|
-
const apiKey =
|
|
3404
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3396
3405
|
const reason = (args.reason || 'rotation').trim().slice(0, 100);
|
|
3397
3406
|
return {
|
|
3398
3407
|
_mode: 'network',
|
|
@@ -3409,7 +3418,7 @@ function handleRotateKey(args) {
|
|
|
3409
3418
|
},
|
|
3410
3419
|
};
|
|
3411
3420
|
}
|
|
3412
|
-
const auth = requireAuth(db, args
|
|
3421
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3413
3422
|
if ('error' in auth)
|
|
3414
3423
|
return auth;
|
|
3415
3424
|
const { user } = auth;
|
|
@@ -3433,12 +3442,12 @@ function handleRotateKey(args) {
|
|
|
3433
3442
|
async function handleReferral(args) {
|
|
3434
3443
|
// RFC-003 Batch 2:NETWORK 模式 → webaz.xyz 真网络聚合(Bearer api_key);SANDBOX 走本地。
|
|
3435
3444
|
if (toolBackend('webaz_referral') === 'network') {
|
|
3436
|
-
const apiKey =
|
|
3445
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3437
3446
|
if (!apiKey)
|
|
3438
3447
|
return { error: 'api_key required' };
|
|
3439
3448
|
return await apiCall('/api/referral/me', { apiKey });
|
|
3440
3449
|
}
|
|
3441
|
-
const auth = requireAuth(db, args
|
|
3450
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3442
3451
|
if ('error' in auth)
|
|
3443
3452
|
return auth;
|
|
3444
3453
|
const { user } = auth;
|
|
@@ -3488,10 +3497,8 @@ async function handleReferral(args) {
|
|
|
3488
3497
|
grand_total: byLevel[1].total + byLevel[2].total + byLevel[3].total,
|
|
3489
3498
|
},
|
|
3490
3499
|
binary: {
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
platform_left: permaCode ? `/?placement=${permaCode}&side=left` : null, // 仅 PV 条线
|
|
3494
|
-
platform_right: permaCode ? `/?placement=${permaCode}&side=right` : null,
|
|
3500
|
+
// pre-public 去左右码:只暴露唯一的推荐码;放置侧别由系统自动决定(无 left/right 选择)
|
|
3501
|
+
referral_link: permaCode ? `/i/${permaCode}` : null,
|
|
3495
3502
|
total_left_pv: Number(me?.total_left_pv ?? 0),
|
|
3496
3503
|
total_right_pv: Number(me?.total_right_pv ?? 0),
|
|
3497
3504
|
pair_volume: pair,
|
|
@@ -3540,23 +3547,21 @@ async function handleReferral(args) {
|
|
|
3540
3547
|
async function handleShareLink(args) {
|
|
3541
3548
|
// RFC-003 #1122:NETWORK 模式 → 调 webaz.xyz 的 /api/share-link(服务端同款计算);SANDBOX 走本地。
|
|
3542
3549
|
if (toolBackend('webaz_share_link') === 'network') {
|
|
3543
|
-
const apiKey =
|
|
3550
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3544
3551
|
if (!apiKey)
|
|
3545
3552
|
return { error: 'api_key required' };
|
|
3546
3553
|
if (!args.product_id)
|
|
3547
3554
|
return { error: 'product_id required' };
|
|
3555
|
+
// pre-public 去左右码:不再向 /api/share-link 转发 side(放置永远自动)
|
|
3548
3556
|
const qs = new URLSearchParams({ product_id: String(args.product_id) });
|
|
3549
|
-
if (args.side)
|
|
3550
|
-
qs.set('side', String(args.side));
|
|
3551
3557
|
return await apiCall('/api/share-link?' + qs.toString(), { apiKey });
|
|
3552
3558
|
}
|
|
3553
|
-
const auth = requireAuth(db, args
|
|
3559
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3554
3560
|
if ('error' in auth)
|
|
3555
3561
|
return auth;
|
|
3556
3562
|
const { user } = auth;
|
|
3557
3563
|
const userId = user.id;
|
|
3558
3564
|
const productId = args.product_id;
|
|
3559
|
-
const sideArg = args.side || 'auto';
|
|
3560
3565
|
// RFC-002 §3.5 valuation-layer gate — share_link generation requires opt-in
|
|
3561
3566
|
const optIn = db.prepare("SELECT rewards_opted_in FROM users WHERE id = ?").get(userId)?.rewards_opted_in ?? 0;
|
|
3562
3567
|
if (optIn !== 1) {
|
|
@@ -3589,32 +3594,7 @@ async function handleShareLink(args) {
|
|
|
3589
3594
|
const product = db.prepare("SELECT id, title, price, commission_rate FROM products WHERE id = ? AND status='active'").get(productId);
|
|
3590
3595
|
if (!product)
|
|
3591
3596
|
return { error: '商品不存在或已下架' };
|
|
3592
|
-
|
|
3593
|
-
if (sideArg === 'left' || sideArg === 'right') {
|
|
3594
|
-
side = sideArg;
|
|
3595
|
-
}
|
|
3596
|
-
else {
|
|
3597
|
-
// auto = 与 PWA pickPreferredSide 对齐:尊重 placement_pref(team_count | pv_count)
|
|
3598
|
-
// 老版只看 total_left_pv vs total_right_pv,team_count 用户被错算
|
|
3599
|
-
const u = db.prepare("SELECT placement_pref, total_left_pv, total_right_pv, left_count, right_count FROM users WHERE id = ?")
|
|
3600
|
-
.get(userId);
|
|
3601
|
-
const pref = u?.placement_pref || 'team_count';
|
|
3602
|
-
if (pref === 'pv_count') {
|
|
3603
|
-
const since = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString().slice(0, 19).replace('T', ' ');
|
|
3604
|
-
const w = db.prepare(`SELECT COALESCE(SUM(consumed_left_pv),0) AS l, COALESCE(SUM(consumed_right_pv),0) AS r
|
|
3605
|
-
FROM binary_score_records WHERE user_id = ? AND created_at >= ?`)
|
|
3606
|
-
.get(userId, since);
|
|
3607
|
-
const leftPv = Number(u?.total_left_pv ?? 0) + Number(w.l);
|
|
3608
|
-
const rightPv = Number(u?.total_right_pv ?? 0) + Number(w.r);
|
|
3609
|
-
side = leftPv <= rightPv ? 'left' : 'right';
|
|
3610
|
-
}
|
|
3611
|
-
else {
|
|
3612
|
-
// team_count: 整棵子树人数(增量维护的 left_count/right_count,与 PWA pickPreferredSide 对齐)。
|
|
3613
|
-
// 2026-06-04 修:旧版沿单条脊链数(countLeg)名实不符 → 选边失真。分享链接的 side 会被注册时
|
|
3614
|
-
// 当 placement_side 显式采用,必须与 PWA joinPowerLeg 用同一指标,否则两路径不一致。
|
|
3615
|
-
side = (Number(u?.left_count ?? 0) <= Number(u?.right_count ?? 0)) ? 'left' : 'right';
|
|
3616
|
-
}
|
|
3617
|
-
}
|
|
3597
|
+
// pre-public 去左右码:分享链接不再携带 side(放置侧别由注册时系统自动决定)
|
|
3618
3598
|
const completed = db.prepare("SELECT COUNT(*) as n FROM orders WHERE buyer_id = ? AND status = 'completed'").get(userId).n;
|
|
3619
3599
|
const override = db.prepare("SELECT l1_share_override FROM users WHERE id = ?").get(userId)?.l1_share_override ?? 0;
|
|
3620
3600
|
const canL1 = override === 1 || (override === 0 && completed > 0);
|
|
@@ -3623,13 +3603,12 @@ async function handleShareLink(args) {
|
|
|
3623
3603
|
const permaCode = db.prepare("SELECT permanent_code FROM users WHERE id = ?").get(userId)?.permanent_code || null;
|
|
3624
3604
|
if (!permaCode)
|
|
3625
3605
|
return { error: 'permanent_code_missing — cannot build a share link; re-register or contact support', error_code: 'PERMANENT_CODE_MISSING' };
|
|
3626
|
-
const link = `/?ref=${permaCode}
|
|
3606
|
+
const link = `/?ref=${permaCode}#order-product/${productId}`;
|
|
3627
3607
|
return {
|
|
3628
3608
|
product: { id: product.id, title: product.title, price: product.price, commission_rate: rate },
|
|
3629
3609
|
share_link: link,
|
|
3630
3610
|
full_url_hint: 'Prepend webaz.xyz (production) or http://localhost:3000 (local) to get the absolute URL',
|
|
3631
|
-
|
|
3632
|
-
binary_explanation: `New user via this link → placed in your ${side === 'left' ? '🔵 left' : '🟢 right'} subtree (tail anchor)`,
|
|
3611
|
+
placement_note: 'New user via this link → placement is recorded automatically by the system (no left/right choice).',
|
|
3633
3612
|
commission_eligibility: canL1
|
|
3634
3613
|
? `You will earn 3-tier commission: L1=${(rate * 0.70 * 100).toFixed(1)}% L2=${(rate * 0.20 * 100).toFixed(1)}% L3=${(rate * 0.10 * 100).toFixed(1)}% of sale price`
|
|
3635
3614
|
: 'You are NOT verified yet (need 1 completed purchase). 3-tier commission will be skipped, but points-matching still builds.',
|
|
@@ -3640,7 +3619,7 @@ async function handleShareLink(args) {
|
|
|
3640
3619
|
async function handleBlocklist(args) {
|
|
3641
3620
|
// RFC-003 Batch 2:NETWORK 模式 → webaz.xyz 真网络(Bearer api_key);SANDBOX 走本地。
|
|
3642
3621
|
if (toolBackend('webaz_blocklist') === 'network') {
|
|
3643
|
-
const apiKey =
|
|
3622
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3644
3623
|
if (!apiKey)
|
|
3645
3624
|
return { error: 'api_key required' };
|
|
3646
3625
|
const act = String(args.action || '');
|
|
@@ -3655,7 +3634,7 @@ async function handleBlocklist(args) {
|
|
|
3655
3634
|
return await apiCall('/api/blocklist/' + uid, { method: 'DELETE', apiKey });
|
|
3656
3635
|
return { error: `unknown action: ${act}` };
|
|
3657
3636
|
}
|
|
3658
|
-
const auth = requireAuth(db, args
|
|
3637
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3659
3638
|
if ('error' in auth)
|
|
3660
3639
|
return auth;
|
|
3661
3640
|
const { user } = auth;
|
|
@@ -3694,7 +3673,7 @@ async function handleBlocklist(args) {
|
|
|
3694
3673
|
async function handleFollows(args) {
|
|
3695
3674
|
// RFC-003 Batch 2:NETWORK 模式 → webaz.xyz 真网络(Bearer api_key);SANDBOX 走本地。
|
|
3696
3675
|
if (toolBackend('webaz_follows') === 'network') {
|
|
3697
|
-
const apiKey =
|
|
3676
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3698
3677
|
if (!apiKey)
|
|
3699
3678
|
return { error: 'api_key required' };
|
|
3700
3679
|
const act = String(args.action || '');
|
|
@@ -3711,7 +3690,7 @@ async function handleFollows(args) {
|
|
|
3711
3690
|
return await apiCall('/api/follows/' + uid + '/status', { apiKey });
|
|
3712
3691
|
return { error: `unknown action: ${act}` };
|
|
3713
3692
|
}
|
|
3714
|
-
const auth = requireAuth(db, args
|
|
3693
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3715
3694
|
if ('error' in auth)
|
|
3716
3695
|
return auth;
|
|
3717
3696
|
const { user } = auth;
|
|
@@ -3760,7 +3739,7 @@ async function handleNearby(args) {
|
|
|
3760
3739
|
const action = String(args.action || '');
|
|
3761
3740
|
// RFC-003 Batch 1:NETWORK 模式 → 调 webaz.xyz 真网络(Bearer api_key);SANDBOX 走本地。
|
|
3762
3741
|
if (toolBackend('webaz_nearby') === 'network') {
|
|
3763
|
-
const apiKey =
|
|
3742
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3764
3743
|
if (!apiKey)
|
|
3765
3744
|
return { error: 'api_key required' };
|
|
3766
3745
|
if (action === 'set_location')
|
|
@@ -3778,7 +3757,7 @@ async function handleNearby(args) {
|
|
|
3778
3757
|
}
|
|
3779
3758
|
return { error: `unknown action: ${action}` };
|
|
3780
3759
|
}
|
|
3781
|
-
const auth = requireAuth(db, args
|
|
3760
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3782
3761
|
if ('error' in auth)
|
|
3783
3762
|
return auth;
|
|
3784
3763
|
const { user } = auth;
|
|
@@ -3829,7 +3808,7 @@ async function handleNearby(args) {
|
|
|
3829
3808
|
async function handleDefaultAddress(args) {
|
|
3830
3809
|
// RFC-003 Batch 2:NETWORK 模式 → webaz.xyz 真网络(Bearer api_key);SANDBOX 走本地。
|
|
3831
3810
|
if (toolBackend('webaz_default_address') === 'network') {
|
|
3832
|
-
const apiKey =
|
|
3811
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3833
3812
|
if (!apiKey)
|
|
3834
3813
|
return { error: 'api_key required' };
|
|
3835
3814
|
const act = String(args.action || '');
|
|
@@ -3848,7 +3827,7 @@ async function handleDefaultAddress(args) {
|
|
|
3848
3827
|
}
|
|
3849
3828
|
return { error: `unknown action: ${act}` };
|
|
3850
3829
|
}
|
|
3851
|
-
const auth = requireAuth(db, args
|
|
3830
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3852
3831
|
if ('error' in auth)
|
|
3853
3832
|
return auth;
|
|
3854
3833
|
const { user } = auth;
|
|
@@ -3889,7 +3868,7 @@ async function handleShareables(args) {
|
|
|
3889
3868
|
const action = String(args.action || '');
|
|
3890
3869
|
// RFC-003 Batch 1:NETWORK 模式 → 调 webaz.xyz 真网络(Bearer api_key);SANDBOX 走本地。
|
|
3891
3870
|
if (toolBackend('webaz_shareables') === 'network') {
|
|
3892
|
-
const apiKey =
|
|
3871
|
+
const apiKey = resolveMcpApiKey(args);
|
|
3893
3872
|
if (!apiKey)
|
|
3894
3873
|
return { error: 'api_key required' };
|
|
3895
3874
|
if (action === 'list_mine')
|
|
@@ -3917,7 +3896,7 @@ async function handleShareables(args) {
|
|
|
3917
3896
|
}
|
|
3918
3897
|
return { error: `unknown action: ${action}` };
|
|
3919
3898
|
}
|
|
3920
|
-
const auth = requireAuth(db, args
|
|
3899
|
+
const auth = requireAuth(db, resolveMcpApiKey(args));
|
|
3921
3900
|
if ('error' in auth)
|
|
3922
3901
|
return auth;
|
|
3923
3902
|
const { user } = auth;
|
|
@@ -4073,7 +4052,7 @@ async function pwaApi(method, path, apiKey, body) {
|
|
|
4073
4052
|
}
|
|
4074
4053
|
}
|
|
4075
4054
|
async function handleSecondhand(args) {
|
|
4076
|
-
const apiKey =
|
|
4055
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4077
4056
|
const action = String(args.action || '');
|
|
4078
4057
|
const isPublic = action === 'browse' || action === 'detail';
|
|
4079
4058
|
if (!isPublic) {
|
|
@@ -4144,7 +4123,7 @@ async function handleSecondhand(args) {
|
|
|
4144
4123
|
}
|
|
4145
4124
|
}
|
|
4146
4125
|
async function handleTrial(args) {
|
|
4147
|
-
const apiKey =
|
|
4126
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4148
4127
|
const action = String(args.action || '');
|
|
4149
4128
|
const isPublic = action === 'get_campaign';
|
|
4150
4129
|
if (!isPublic) {
|
|
@@ -4197,7 +4176,7 @@ async function handleTrial(args) {
|
|
|
4197
4176
|
}
|
|
4198
4177
|
}
|
|
4199
4178
|
async function handleSkillMarket(args) {
|
|
4200
|
-
const apiKey =
|
|
4179
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4201
4180
|
const action = String(args.action || '');
|
|
4202
4181
|
const isPublic = action === 'list' || action === 'detail';
|
|
4203
4182
|
if (!isPublic) {
|
|
@@ -4270,7 +4249,7 @@ async function handleSkillMarket(args) {
|
|
|
4270
4249
|
}
|
|
4271
4250
|
}
|
|
4272
4251
|
async function handleRfq(args) {
|
|
4273
|
-
const apiKey =
|
|
4252
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4274
4253
|
const action = String(args.action || '');
|
|
4275
4254
|
if (!apiKey)
|
|
4276
4255
|
return { error: 'api_key required' };
|
|
@@ -4319,7 +4298,7 @@ async function handleRfq(args) {
|
|
|
4319
4298
|
}
|
|
4320
4299
|
}
|
|
4321
4300
|
async function handleBid(args) {
|
|
4322
|
-
const apiKey =
|
|
4301
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4323
4302
|
const action = String(args.action || '');
|
|
4324
4303
|
if (!apiKey)
|
|
4325
4304
|
return { error: 'api_key required' };
|
|
@@ -4393,7 +4372,7 @@ async function handleBid(args) {
|
|
|
4393
4372
|
}
|
|
4394
4373
|
}
|
|
4395
4374
|
async function handleChat(args) {
|
|
4396
|
-
const apiKey =
|
|
4375
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4397
4376
|
const action = String(args.action || '');
|
|
4398
4377
|
if (!apiKey)
|
|
4399
4378
|
return { error: 'api_key required' };
|
|
@@ -4435,7 +4414,7 @@ async function handleChat(args) {
|
|
|
4435
4414
|
}
|
|
4436
4415
|
}
|
|
4437
4416
|
async function handleAutoBidSkill(args) {
|
|
4438
|
-
const apiKey =
|
|
4417
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4439
4418
|
const action = String(args.action || '');
|
|
4440
4419
|
if (!apiKey)
|
|
4441
4420
|
return { error: 'api_key required' };
|
|
@@ -4558,7 +4537,7 @@ async function handleCharity(args) {
|
|
|
4558
4537
|
return readEndpoint('webaz_charity', '/charity/leaderboard');
|
|
4559
4538
|
if (action === 'fund')
|
|
4560
4539
|
return readEndpoint('webaz_charity', '/charity/fund');
|
|
4561
|
-
const apiKey =
|
|
4540
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4562
4541
|
if (!apiKey)
|
|
4563
4542
|
return { error: 'api_key required for this action' };
|
|
4564
4543
|
if (toolBackend('webaz_charity') !== 'network') {
|
|
@@ -4621,7 +4600,7 @@ async function handleP2pProduct(args) {
|
|
|
4621
4600
|
return { error: String(e.message) };
|
|
4622
4601
|
}
|
|
4623
4602
|
}
|
|
4624
|
-
const apiKey =
|
|
4603
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4625
4604
|
if (!apiKey)
|
|
4626
4605
|
return { error: 'api_key required for create/patch' };
|
|
4627
4606
|
const auth = requireAuth(db, apiKey);
|
|
@@ -4648,7 +4627,7 @@ async function handleP2pProduct(args) {
|
|
|
4648
4627
|
return { error: `unknown action: ${action}` };
|
|
4649
4628
|
}
|
|
4650
4629
|
async function handleLike(args) {
|
|
4651
|
-
const apiKey =
|
|
4630
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4652
4631
|
const action = String(args.action || '');
|
|
4653
4632
|
const sid = String(args.shareable_id || '');
|
|
4654
4633
|
if (!apiKey || !sid)
|
|
@@ -4674,7 +4653,7 @@ async function handleLeaderboard(args) {
|
|
|
4674
4653
|
return readEndpoint('webaz_leaderboard', '/leaderboard?kind=' + kind + '&limit=' + limit);
|
|
4675
4654
|
}
|
|
4676
4655
|
async function handleAuction(args) {
|
|
4677
|
-
const apiKey =
|
|
4656
|
+
const apiKey = resolveMcpApiKey(args);
|
|
4678
4657
|
const action = String(args.action || '');
|
|
4679
4658
|
if (!apiKey)
|
|
4680
4659
|
return { error: 'api_key required' };
|
|
@@ -5132,7 +5111,7 @@ function addHours(date, hours) {
|
|
|
5132
5111
|
function recordToolCall(tool, args, result, latencyMs) {
|
|
5133
5112
|
let userId = null;
|
|
5134
5113
|
try {
|
|
5135
|
-
const apiKey = args
|
|
5114
|
+
const apiKey = resolveMcpApiKey(args);
|
|
5136
5115
|
if (apiKey) {
|
|
5137
5116
|
const row = db.prepare('SELECT id FROM users WHERE api_key = ?').get(apiKey);
|
|
5138
5117
|
if (row)
|