ebay-mcp-remote-edition 3.2.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +261 -1
- package/build/api/analytics-and-report/analytics.js +4 -4
- package/build/api/client-trading.js +2 -2
- package/build/api/communication/feedback.js +5 -5
- package/build/api/communication/message.js +5 -5
- package/build/api/communication/negotiation.js +3 -3
- package/build/api/communication/notification.js +21 -21
- package/build/api/listing-management/inventory.js +36 -36
- package/build/api/listing-metadata/metadata.js +24 -24
- package/build/auth/oauth.js +2 -2
- package/build/auth/token-verifier.js +3 -3
- package/build/server-http.js +18 -1
- package/build/tools/index.js +5 -5
- package/build/validation/effective-context.js +77 -0
- package/build/validation/providers/ebay-sold.js +96 -51
- package/build/validation/providers/ebay.js +115 -57
- package/build/validation/providers/query-utils.js +577 -0
- package/build/validation/providers/research.js +16 -0
- package/build/validation/providers/social.js +681 -2
- package/build/validation/providers/terapeak.js +30 -0
- package/build/validation/recommendation.js +33 -10
- package/build/validation/run-validation.js +279 -31
- package/build/validation/schemas.js +62 -15
- package/package.json +22 -20
|
@@ -1,31 +1,11 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
1
2
|
import { getBaseUrl } from '../../config/environment.js';
|
|
3
|
+
import { buildResolvedBrowseQueryPlan } from './query-utils.js';
|
|
2
4
|
function round(value) {
|
|
3
5
|
return Math.round(value * 100) / 100;
|
|
4
6
|
}
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
const addTerms = (values, maxTerms = values.length) => {
|
|
8
|
-
for (const value of values) {
|
|
9
|
-
if (!value)
|
|
10
|
-
continue;
|
|
11
|
-
const normalized = value.trim();
|
|
12
|
-
if (!normalized)
|
|
13
|
-
continue;
|
|
14
|
-
terms.add(normalized);
|
|
15
|
-
if (terms.size >= maxTerms) {
|
|
16
|
-
break;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
addTerms([request.item.name], 1);
|
|
21
|
-
addTerms(request.item.canonicalArtists, 3);
|
|
22
|
-
addTerms(request.item.relatedAlbums, 5);
|
|
23
|
-
addTerms(request.item.variation, 7);
|
|
24
|
-
addTerms([request.validation.validationType], 8);
|
|
25
|
-
return Array.from(terms);
|
|
26
|
-
}
|
|
27
|
-
export function buildEbayValidationQuery(request) {
|
|
28
|
-
return buildQueryTerms(request).join(' ').replace(/\s+/g, ' ').trim();
|
|
7
|
+
export function buildEbayValidationQueries(request) {
|
|
8
|
+
return buildResolvedBrowseQueryPlan(request).queryPlan.map((candidate) => candidate.query);
|
|
29
9
|
}
|
|
30
10
|
function deriveTrend(current, previous, fallback) {
|
|
31
11
|
if (current === null || previous === null || previous <= 0) {
|
|
@@ -48,8 +28,31 @@ function median(values) {
|
|
|
48
28
|
}
|
|
49
29
|
return sorted[middle];
|
|
50
30
|
}
|
|
31
|
+
function getAxiosFailureDebug(error) {
|
|
32
|
+
if (!axios.isAxiosError(error)) {
|
|
33
|
+
return {
|
|
34
|
+
responseStatus: null,
|
|
35
|
+
responseBodyExcerpt: null,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const responseStatus = error.response?.status ?? null;
|
|
39
|
+
const rawBody = error.response?.data;
|
|
40
|
+
if (rawBody === undefined) {
|
|
41
|
+
return {
|
|
42
|
+
responseStatus,
|
|
43
|
+
responseBodyExcerpt: null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const bodyText = typeof rawBody === 'string' ? rawBody : JSON.stringify(rawBody, null, 2);
|
|
47
|
+
return {
|
|
48
|
+
responseStatus,
|
|
49
|
+
responseBodyExcerpt: bodyText.slice(0, 500),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
51
52
|
export async function getEbayValidationSignals(api, request) {
|
|
52
|
-
const
|
|
53
|
+
const { queryPlan, queryResolution } = buildResolvedBrowseQueryPlan(request);
|
|
54
|
+
const queryCandidates = queryPlan.map((candidate) => candidate.query);
|
|
55
|
+
const ebayQuery = queryCandidates[0] ?? '';
|
|
53
56
|
const fallbackTrend = request.validation.currentMetrics.marketPriceTrend || 'Stable';
|
|
54
57
|
const emptyResult = {
|
|
55
58
|
avgWatchersPerListing: null,
|
|
@@ -59,6 +62,13 @@ export async function getEbayValidationSignals(api, request) {
|
|
|
59
62
|
competitionLevel: null,
|
|
60
63
|
marketPriceTrend: fallbackTrend,
|
|
61
64
|
ebayQuery,
|
|
65
|
+
queryCandidates,
|
|
66
|
+
selectedQuery: ebayQuery || undefined,
|
|
67
|
+
selectedQueryTier: ebayQuery ? 1 : null,
|
|
68
|
+
queryDiagnostics: [],
|
|
69
|
+
selectionReason: queryCandidates.length
|
|
70
|
+
? 'Cleaned browse candidates were generated, but none have been evaluated yet.'
|
|
71
|
+
: 'No valid browse query candidates were generated after sanitization and semantic filtering.',
|
|
62
72
|
sampleSize: 0,
|
|
63
73
|
soldVelocity: {
|
|
64
74
|
day1Sold: request.validation.currentMetrics.day1Sold,
|
|
@@ -68,45 +78,93 @@ export async function getEbayValidationSignals(api, request) {
|
|
|
68
78
|
day5Sold: request.validation.currentMetrics.day5Sold,
|
|
69
79
|
daysTracked: request.validation.currentMetrics.daysTracked,
|
|
70
80
|
},
|
|
81
|
+
queryResolution,
|
|
71
82
|
};
|
|
72
|
-
if (
|
|
83
|
+
if (queryCandidates.length === 0) {
|
|
73
84
|
return emptyResult;
|
|
74
85
|
}
|
|
75
86
|
try {
|
|
76
87
|
const environment = api.getAuthClient().getConfig().environment;
|
|
77
|
-
const browseUrl =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
const browseUrl = new URL('/buy/browse/v1/item_summary/search', getBaseUrl(environment)).toString();
|
|
89
|
+
let selectedResult = emptyResult;
|
|
90
|
+
let bestScore = -1;
|
|
91
|
+
const queryDiagnostics = [];
|
|
92
|
+
for (const [index, query] of queryCandidates.entries()) {
|
|
93
|
+
const response = await api.getAuthClient().getWithFullUrl(browseUrl, {
|
|
94
|
+
q: query,
|
|
95
|
+
limit: 25,
|
|
96
|
+
sort: 'newlyListed',
|
|
97
|
+
});
|
|
98
|
+
const itemSummaries = response.itemSummaries ?? [];
|
|
99
|
+
const prices = itemSummaries
|
|
100
|
+
.map((item) => Number(item.price?.value ?? Number.NaN))
|
|
101
|
+
.filter((value) => Number.isFinite(value) && value > 0);
|
|
102
|
+
const shipping = itemSummaries
|
|
103
|
+
.map((item) => Number(item.shippingOptions?.[0]?.shippingCost?.value ?? Number.NaN))
|
|
104
|
+
.filter((value) => Number.isFinite(value) && value >= 0);
|
|
105
|
+
const marketPriceUsd = median(prices);
|
|
106
|
+
const avgShippingCostUsd = shipping.length > 0
|
|
107
|
+
? shipping.reduce((sum, value) => sum + value, 0) / shipping.length
|
|
108
|
+
: null;
|
|
109
|
+
const totalListings = typeof response.total === 'number' && Number.isFinite(response.total)
|
|
110
|
+
? response.total
|
|
111
|
+
: itemSummaries.length;
|
|
112
|
+
const attemptScore = Math.max(itemSummaries.length, totalListings);
|
|
113
|
+
queryDiagnostics.push({
|
|
114
|
+
query,
|
|
115
|
+
tier: index + 1,
|
|
116
|
+
family: queryPlan[index]?.family,
|
|
117
|
+
itemSummaryCount: itemSummaries.length,
|
|
118
|
+
totalListings,
|
|
119
|
+
});
|
|
120
|
+
if (attemptScore <= bestScore) {
|
|
121
|
+
if (itemSummaries.length >= 5 || totalListings >= 5) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
bestScore = attemptScore;
|
|
127
|
+
selectedResult = {
|
|
128
|
+
avgWatchersPerListing: null,
|
|
129
|
+
preOrderListingsCount: totalListings,
|
|
130
|
+
marketPriceUsd: marketPriceUsd === null ? null : round(marketPriceUsd),
|
|
131
|
+
avgShippingCostUsd: avgShippingCostUsd === null ? null : round(avgShippingCostUsd),
|
|
132
|
+
competitionLevel: totalListings,
|
|
133
|
+
marketPriceTrend: deriveTrend(marketPriceUsd, request.validation.currentMetrics.marketPriceUsd, fallbackTrend),
|
|
134
|
+
ebayQuery: query,
|
|
135
|
+
queryCandidates,
|
|
136
|
+
selectedQuery: query,
|
|
137
|
+
selectedQueryTier: index + 1,
|
|
138
|
+
queryDiagnostics: [...queryDiagnostics],
|
|
139
|
+
selectionReason: itemSummaries.length >= 5 || totalListings >= 5
|
|
140
|
+
? 'Selected because this cleaned browse candidate produced sufficient listing depth.'
|
|
141
|
+
: attemptScore > 0
|
|
142
|
+
? 'Selected as the strongest cleaned browse fallback after higher-priority candidates returned weaker results.'
|
|
143
|
+
: 'All cleaned browse candidates seen so far returned zero results; keeping the highest-priority candidate for traceability.',
|
|
144
|
+
sampleSize: itemSummaries.length,
|
|
145
|
+
soldVelocity: emptyResult.soldVelocity,
|
|
146
|
+
queryResolution,
|
|
147
|
+
};
|
|
148
|
+
if (itemSummaries.length >= 5 || totalListings >= 5) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
97
152
|
return {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
competitionLevel: totalListings,
|
|
103
|
-
marketPriceTrend: deriveTrend(marketPriceUsd, request.validation.currentMetrics.marketPriceUsd, fallbackTrend),
|
|
104
|
-
ebayQuery,
|
|
105
|
-
sampleSize: itemSummaries.length,
|
|
106
|
-
soldVelocity: emptyResult.soldVelocity,
|
|
153
|
+
...selectedResult,
|
|
154
|
+
queryDiagnostics,
|
|
155
|
+
selectionReason: selectedResult.selectionReason ??
|
|
156
|
+
'Browse selection completed without a stronger candidate than the highest-priority cleaned query.',
|
|
107
157
|
};
|
|
108
158
|
}
|
|
109
|
-
catch {
|
|
110
|
-
|
|
159
|
+
catch (error) {
|
|
160
|
+
const failureDebug = getAxiosFailureDebug(error);
|
|
161
|
+
return {
|
|
162
|
+
...emptyResult,
|
|
163
|
+
selectionReason: 'Browse query execution failed before result selection could complete; returning the cleaned fallback candidate set for debug traceability.',
|
|
164
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
165
|
+
responseStatus: failureDebug.responseStatus,
|
|
166
|
+
responseBodyExcerpt: failureDebug.responseBodyExcerpt,
|
|
167
|
+
queryResolution,
|
|
168
|
+
};
|
|
111
169
|
}
|
|
112
170
|
}
|