@xiawan-play/steam-tools-mcp 0.3.0 → 0.3.2
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 +70 -48
- package/dist/server.js +847 -751
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -19504,8 +19504,8 @@ var require_subresource_integrity = __commonJS({
|
|
|
19504
19504
|
if (parsedMetadata.length === 0) {
|
|
19505
19505
|
return true;
|
|
19506
19506
|
}
|
|
19507
|
-
const
|
|
19508
|
-
for (const item of
|
|
19507
|
+
const metadata2 = getStrongestMetadata(parsedMetadata);
|
|
19508
|
+
for (const item of metadata2) {
|
|
19509
19509
|
const algorithm = item.alg;
|
|
19510
19510
|
const expectedValue = item.val;
|
|
19511
19511
|
const actualValue = applyAlgorithmToBytes(algorithm, bytes);
|
|
@@ -19544,9 +19544,9 @@ var require_subresource_integrity = __commonJS({
|
|
|
19544
19544
|
}
|
|
19545
19545
|
return result;
|
|
19546
19546
|
}
|
|
19547
|
-
function parseMetadata(
|
|
19547
|
+
function parseMetadata(metadata2) {
|
|
19548
19548
|
const result = [];
|
|
19549
|
-
for (const item of
|
|
19549
|
+
for (const item of metadata2.split(" ")) {
|
|
19550
19550
|
const expressionAndOptions = item.split("?", 1);
|
|
19551
19551
|
const algorithmExpression = expressionAndOptions[0];
|
|
19552
19552
|
let base64Value = "";
|
|
@@ -19558,11 +19558,11 @@ var require_subresource_integrity = __commonJS({
|
|
|
19558
19558
|
if (algorithmAndValue[1]) {
|
|
19559
19559
|
base64Value = algorithmAndValue[1];
|
|
19560
19560
|
}
|
|
19561
|
-
const
|
|
19561
|
+
const metadata3 = {
|
|
19562
19562
|
alg: algorithm,
|
|
19563
19563
|
val: base64Value
|
|
19564
19564
|
};
|
|
19565
|
-
result.push(
|
|
19565
|
+
result.push(metadata3);
|
|
19566
19566
|
}
|
|
19567
19567
|
return result;
|
|
19568
19568
|
}
|
|
@@ -34612,6 +34612,80 @@ function applyGeneratedToolTitles(spec2) {
|
|
|
34612
34612
|
return spec2;
|
|
34613
34613
|
}
|
|
34614
34614
|
|
|
34615
|
+
// package.json
|
|
34616
|
+
var package_default = {
|
|
34617
|
+
name: "@xiawan-play/steam-tools-mcp",
|
|
34618
|
+
version: "0.3.2",
|
|
34619
|
+
description: "A Steam MCP server with Chinese-friendly high-level tools for profiles, libraries, game snapshots, achievements, and app discovery.",
|
|
34620
|
+
type: "module",
|
|
34621
|
+
license: "MIT",
|
|
34622
|
+
main: "./dist/server.js",
|
|
34623
|
+
types: "./dist/server.d.ts",
|
|
34624
|
+
exports: {
|
|
34625
|
+
".": {
|
|
34626
|
+
types: "./dist/server.d.ts",
|
|
34627
|
+
default: "./dist/server.js"
|
|
34628
|
+
}
|
|
34629
|
+
},
|
|
34630
|
+
bin: {
|
|
34631
|
+
"steam-tools-mcp": "dist/server.js"
|
|
34632
|
+
},
|
|
34633
|
+
files: [
|
|
34634
|
+
"dist",
|
|
34635
|
+
"docs",
|
|
34636
|
+
"README.md",
|
|
34637
|
+
".env.example"
|
|
34638
|
+
],
|
|
34639
|
+
keywords: [
|
|
34640
|
+
"mcp",
|
|
34641
|
+
"model-context-protocol",
|
|
34642
|
+
"steam",
|
|
34643
|
+
"steam-tools",
|
|
34644
|
+
"steam-web-api",
|
|
34645
|
+
"steamworks"
|
|
34646
|
+
],
|
|
34647
|
+
publishConfig: {
|
|
34648
|
+
access: "public"
|
|
34649
|
+
},
|
|
34650
|
+
repository: {
|
|
34651
|
+
type: "git",
|
|
34652
|
+
url: "git+https://github.com/XiaWan-Play/steam-tools-mcp.git"
|
|
34653
|
+
},
|
|
34654
|
+
homepage: "https://github.com/XiaWan-Play/steam-tools-mcp#readme",
|
|
34655
|
+
bugs: {
|
|
34656
|
+
url: "https://github.com/XiaWan-Play/steam-tools-mcp/issues"
|
|
34657
|
+
},
|
|
34658
|
+
engines: {
|
|
34659
|
+
node: ">=20.0.0"
|
|
34660
|
+
},
|
|
34661
|
+
scripts: {
|
|
34662
|
+
dev: "tsx src/server.ts",
|
|
34663
|
+
build: "tsup src/server.ts --format esm --dts --clean",
|
|
34664
|
+
"check:tool-registry": "tsx scripts/check-tool-registration.ts",
|
|
34665
|
+
start: "node dist/server.js",
|
|
34666
|
+
"sync:steam-spec": "tsx scripts/sync-steam-web-api-spec.ts",
|
|
34667
|
+
prepare: "npm run build"
|
|
34668
|
+
},
|
|
34669
|
+
dependencies: {
|
|
34670
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
34671
|
+
cheerio: "^1.2.0",
|
|
34672
|
+
zod: "^4.3.6"
|
|
34673
|
+
},
|
|
34674
|
+
devDependencies: {
|
|
34675
|
+
"@types/express": "^5.0.3",
|
|
34676
|
+
"@types/node": "^24.6.1",
|
|
34677
|
+
tsup: "^8.5.1",
|
|
34678
|
+
tsx: "^4.20.6",
|
|
34679
|
+
typescript: "^5.9.3"
|
|
34680
|
+
}
|
|
34681
|
+
};
|
|
34682
|
+
|
|
34683
|
+
// src/lib/package-meta.ts
|
|
34684
|
+
var metadata = package_default;
|
|
34685
|
+
var PACKAGE_NAME = metadata.name.includes("/") ? metadata.name.split("/").pop() ?? metadata.name : metadata.name;
|
|
34686
|
+
var PACKAGE_VERSION = metadata.version;
|
|
34687
|
+
var PACKAGE_USER_AGENT = `${PACKAGE_NAME}/${PACKAGE_VERSION}`;
|
|
34688
|
+
|
|
34615
34689
|
// src/normalizers/common.ts
|
|
34616
34690
|
function normalizeScalarInput(value) {
|
|
34617
34691
|
if (value === void 0 || value === null) {
|
|
@@ -35153,11 +35227,11 @@ async function fetchTextResponse(url, timeoutMs) {
|
|
|
35153
35227
|
const controller = new AbortController();
|
|
35154
35228
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
35155
35229
|
try {
|
|
35156
|
-
const response = await
|
|
35230
|
+
const response = await fetchWithProxy(url, {
|
|
35157
35231
|
signal: controller.signal,
|
|
35158
35232
|
headers: {
|
|
35159
35233
|
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
|
|
35160
|
-
"user-agent":
|
|
35234
|
+
"user-agent": PACKAGE_USER_AGENT
|
|
35161
35235
|
}
|
|
35162
35236
|
});
|
|
35163
35237
|
if (!response.ok) {
|
|
@@ -35174,6 +35248,70 @@ async function fetchJsonResponse(url, timeoutMs) {
|
|
|
35174
35248
|
}
|
|
35175
35249
|
|
|
35176
35250
|
// src/services/base/apps.ts
|
|
35251
|
+
function isChineseLikeLocale(locale) {
|
|
35252
|
+
const normalized = normalizeLocale(locale) ?? "";
|
|
35253
|
+
return normalized.startsWith("zh") || normalized.includes("chinese");
|
|
35254
|
+
}
|
|
35255
|
+
function normalizeStoreTitleCandidate(value) {
|
|
35256
|
+
const text = value?.replace(/\s+/g, " ").trim();
|
|
35257
|
+
if (!text) {
|
|
35258
|
+
return void 0;
|
|
35259
|
+
}
|
|
35260
|
+
const patterns = [
|
|
35261
|
+
/^在 Steam 上购买\s+(.+?)\s+立省.*$/u,
|
|
35262
|
+
/^Steam 上的\s+(.+)$/u,
|
|
35263
|
+
/^在 Steam 上下载\s+(.+)$/u,
|
|
35264
|
+
/^Buy\s+(.+?)\s+on Steam$/iu,
|
|
35265
|
+
/^Save .* on\s+(.+?)\s+on Steam$/iu,
|
|
35266
|
+
/^(.+?) on Steam$/iu
|
|
35267
|
+
];
|
|
35268
|
+
for (const pattern of patterns) {
|
|
35269
|
+
const match = text.match(pattern);
|
|
35270
|
+
const candidate = match?.[1]?.trim();
|
|
35271
|
+
if (candidate) {
|
|
35272
|
+
return candidate;
|
|
35273
|
+
}
|
|
35274
|
+
}
|
|
35275
|
+
return text;
|
|
35276
|
+
}
|
|
35277
|
+
function pickStorePageAppName(candidates, locale) {
|
|
35278
|
+
const normalizedCandidates = uniqueStrings(
|
|
35279
|
+
candidates.map((candidate) => normalizeStoreTitleCandidate(candidate)).filter((candidate) => Boolean(candidate))
|
|
35280
|
+
);
|
|
35281
|
+
if (normalizedCandidates.length === 0) {
|
|
35282
|
+
return void 0;
|
|
35283
|
+
}
|
|
35284
|
+
if (isChineseLikeLocale(locale)) {
|
|
35285
|
+
return normalizedCandidates.find((candidate) => containsNonAscii(candidate)) ?? normalizedCandidates[0];
|
|
35286
|
+
}
|
|
35287
|
+
return normalizedCandidates[0];
|
|
35288
|
+
}
|
|
35289
|
+
function shouldFetchStorePageName(existingName, locale) {
|
|
35290
|
+
if (!isChineseLikeLocale(locale)) {
|
|
35291
|
+
return false;
|
|
35292
|
+
}
|
|
35293
|
+
if (!existingName) {
|
|
35294
|
+
return true;
|
|
35295
|
+
}
|
|
35296
|
+
return !containsNonAscii(existingName);
|
|
35297
|
+
}
|
|
35298
|
+
function shouldPreferStorePageName(existingName, candidateName, locale) {
|
|
35299
|
+
if (!candidateName) {
|
|
35300
|
+
return false;
|
|
35301
|
+
}
|
|
35302
|
+
if (!existingName) {
|
|
35303
|
+
return true;
|
|
35304
|
+
}
|
|
35305
|
+
if (!isChineseLikeLocale(locale)) {
|
|
35306
|
+
return false;
|
|
35307
|
+
}
|
|
35308
|
+
const existingHasLocalizedChars = containsNonAscii(existingName);
|
|
35309
|
+
const candidateHasLocalizedChars = containsNonAscii(candidateName);
|
|
35310
|
+
if (existingHasLocalizedChars !== candidateHasLocalizedChars) {
|
|
35311
|
+
return candidateHasLocalizedChars;
|
|
35312
|
+
}
|
|
35313
|
+
return false;
|
|
35314
|
+
}
|
|
35177
35315
|
function createAppRuntimeHelpers(deps) {
|
|
35178
35316
|
const { config, safeInvokeKnownMethod, requireSteamApiKey } = deps;
|
|
35179
35317
|
let appCatalogCache = null;
|
|
@@ -35322,6 +35460,38 @@ function createAppRuntimeHelpers(deps) {
|
|
|
35322
35460
|
locale: normalizedLocale
|
|
35323
35461
|
};
|
|
35324
35462
|
}
|
|
35463
|
+
async function fetchStorePageLocalizedAppName(appid, locale = "schinese") {
|
|
35464
|
+
const normalizedLocale = normalizeLocale(locale) ?? "schinese";
|
|
35465
|
+
const url = new URL(`https://store.steampowered.com/app/${appid}/`);
|
|
35466
|
+
url.searchParams.set("l", normalizedLocale);
|
|
35467
|
+
url.searchParams.set("cc", "cn");
|
|
35468
|
+
const pageText = await fetchTextResponse(url, 3500);
|
|
35469
|
+
const $ = load(pageText);
|
|
35470
|
+
const reviewPropsRaw = $('[data-featuretarget="appreviews"]').first().attr("data-props");
|
|
35471
|
+
let reviewAppName;
|
|
35472
|
+
if (reviewPropsRaw) {
|
|
35473
|
+
try {
|
|
35474
|
+
const reviewProps = asRecord(JSON.parse(reviewPropsRaw));
|
|
35475
|
+
reviewAppName = getStringValue(reviewProps?.appname);
|
|
35476
|
+
} catch {
|
|
35477
|
+
reviewAppName = void 0;
|
|
35478
|
+
}
|
|
35479
|
+
}
|
|
35480
|
+
const localizedName = pickStorePageAppName(
|
|
35481
|
+
[
|
|
35482
|
+
reviewAppName,
|
|
35483
|
+
$("#appHubAppName").first().text(),
|
|
35484
|
+
$(".apphub_AppName").first().text(),
|
|
35485
|
+
$('meta[property="og:title"]').attr("content"),
|
|
35486
|
+
$("title").first().text()
|
|
35487
|
+
],
|
|
35488
|
+
normalizedLocale
|
|
35489
|
+
);
|
|
35490
|
+
return {
|
|
35491
|
+
localizedName,
|
|
35492
|
+
locale: normalizedLocale
|
|
35493
|
+
};
|
|
35494
|
+
}
|
|
35325
35495
|
async function fetchLocalizedStoreAppName(appid, locale) {
|
|
35326
35496
|
const cacheKey = `${appid}:${locale}`;
|
|
35327
35497
|
const cached = localizedAppNameCache.get(cacheKey);
|
|
@@ -35330,10 +35500,25 @@ function createAppRuntimeHelpers(deps) {
|
|
|
35330
35500
|
return cached.value;
|
|
35331
35501
|
}
|
|
35332
35502
|
const details = await fetchStoreAppDetailsSummary(appid, locale);
|
|
35333
|
-
|
|
35503
|
+
let localizedName = details?.name;
|
|
35504
|
+
let source = localizedName ? "storeAppDetails" : "fallback";
|
|
35505
|
+
if (shouldFetchStorePageName(localizedName, locale)) {
|
|
35506
|
+
try {
|
|
35507
|
+
const pageName = await fetchStorePageLocalizedAppName(appid, locale);
|
|
35508
|
+
if (shouldPreferStorePageName(
|
|
35509
|
+
localizedName,
|
|
35510
|
+
pageName.localizedName,
|
|
35511
|
+
pageName.locale
|
|
35512
|
+
)) {
|
|
35513
|
+
localizedName = pageName.localizedName;
|
|
35514
|
+
source = localizedName ? "storePage" : source;
|
|
35515
|
+
}
|
|
35516
|
+
} catch {
|
|
35517
|
+
}
|
|
35518
|
+
}
|
|
35334
35519
|
const value = {
|
|
35335
35520
|
localizedName,
|
|
35336
|
-
source
|
|
35521
|
+
source,
|
|
35337
35522
|
locale: details?.locale ?? normalizeLocale(locale) ?? "schinese"
|
|
35338
35523
|
};
|
|
35339
35524
|
localizedAppNameCache.set(cacheKey, {
|
|
@@ -37007,444 +37192,221 @@ async function buildAppSnapshotData(runtime2, input) {
|
|
|
37007
37192
|
};
|
|
37008
37193
|
}
|
|
37009
37194
|
|
|
37010
|
-
// src/services/
|
|
37011
|
-
|
|
37012
|
-
var
|
|
37013
|
-
|
|
37014
|
-
|
|
37015
|
-
|
|
37016
|
-
|
|
37017
|
-
|
|
37018
|
-
|
|
37019
|
-
|
|
37020
|
-
|
|
37021
|
-
|
|
37022
|
-
|
|
37023
|
-
|
|
37195
|
+
// src/services/achievement-guide.ts
|
|
37196
|
+
import { load as load2 } from "cheerio";
|
|
37197
|
+
var STEAM_GUIDE_KEYWORDS = [
|
|
37198
|
+
"achievement",
|
|
37199
|
+
"100%",
|
|
37200
|
+
"all achievements",
|
|
37201
|
+
"guide",
|
|
37202
|
+
"walkthrough",
|
|
37203
|
+
"missable",
|
|
37204
|
+
"coop",
|
|
37205
|
+
"co-op"
|
|
37206
|
+
];
|
|
37207
|
+
var RARITY_BANDS = [
|
|
37208
|
+
{
|
|
37209
|
+
key: "veryRare",
|
|
37210
|
+
label: "Very Rare",
|
|
37211
|
+
minPercent: 0,
|
|
37212
|
+
maxPercent: 5
|
|
37213
|
+
},
|
|
37214
|
+
{
|
|
37215
|
+
key: "rare",
|
|
37216
|
+
label: "Rare",
|
|
37217
|
+
minPercent: 5,
|
|
37218
|
+
maxPercent: 20
|
|
37219
|
+
},
|
|
37220
|
+
{
|
|
37221
|
+
key: "uncommon",
|
|
37222
|
+
label: "Uncommon",
|
|
37223
|
+
minPercent: 20,
|
|
37224
|
+
maxPercent: 50
|
|
37225
|
+
},
|
|
37226
|
+
{
|
|
37227
|
+
key: "common",
|
|
37228
|
+
label: "Common",
|
|
37229
|
+
minPercent: 50,
|
|
37230
|
+
maxPercent: Number.POSITIVE_INFINITY
|
|
37231
|
+
}
|
|
37232
|
+
];
|
|
37233
|
+
function isPresent(value) {
|
|
37234
|
+
return value !== null && value !== void 0;
|
|
37235
|
+
}
|
|
37236
|
+
async function buildAchievementGuideData(runtime2, input) {
|
|
37237
|
+
const overview = await buildGlobalAchievementOverviewData(runtime2, {
|
|
37238
|
+
toolName: input.toolName,
|
|
37239
|
+
appid: input.appid,
|
|
37240
|
+
query: input.query,
|
|
37241
|
+
key: input.key,
|
|
37242
|
+
language: input.language,
|
|
37243
|
+
includeSchemaDetails: input.includeSchemaDetails,
|
|
37244
|
+
topCount: input.topCount
|
|
37024
37245
|
});
|
|
37025
|
-
const
|
|
37026
|
-
const
|
|
37027
|
-
|
|
37246
|
+
const target = asRecord(overview.target);
|
|
37247
|
+
const app = asRecord(target?.app);
|
|
37248
|
+
const overviewSummary = asRecord(overview.summary);
|
|
37249
|
+
const warnings = Array.isArray(overview.warnings) ? [...overview.warnings] : [];
|
|
37250
|
+
const sourceItems = getRecordItems(overview.items);
|
|
37251
|
+
const achievementMap = buildAchievementMap(sourceItems);
|
|
37252
|
+
const indexUrls = app && getStringValue(app.appid) ? buildSteamGuideIndexUrls(getStringValue(app.appid)) : [];
|
|
37253
|
+
const selectedGuides = await loadGuideCandidates(
|
|
37254
|
+
runtime2,
|
|
37255
|
+
indexUrls,
|
|
37256
|
+
input.maxGuides,
|
|
37257
|
+
warnings
|
|
37258
|
+
);
|
|
37259
|
+
const guideAnalyses = await Promise.all(
|
|
37260
|
+
selectedGuides.map(async (guide) => {
|
|
37261
|
+
try {
|
|
37262
|
+
const html = await fetchSteamCommunityHtml(guide.url, runtime2.config.timeoutMs);
|
|
37263
|
+
return analyzeGuidePage(html, guide, achievementMap);
|
|
37264
|
+
} catch (error) {
|
|
37265
|
+
warnings.push(
|
|
37266
|
+
`Steam Guide fetch failed for ${guide.url}: ${error instanceof Error ? error.message : String(error)}`
|
|
37267
|
+
);
|
|
37268
|
+
return null;
|
|
37269
|
+
}
|
|
37270
|
+
})
|
|
37271
|
+
);
|
|
37272
|
+
const validGuides = guideAnalyses.filter(
|
|
37273
|
+
(guide) => Boolean(guide)
|
|
37274
|
+
);
|
|
37275
|
+
const guideFacts = dedupeGuideFacts(
|
|
37276
|
+
validGuides.flatMap((guide) => guide.facts)
|
|
37277
|
+
).slice(0, input.maxGuideFacts);
|
|
37278
|
+
const achievementEvidence = buildAchievementEvidence(
|
|
37279
|
+
validGuides,
|
|
37280
|
+
input.maxEvidencePerAchievement
|
|
37281
|
+
);
|
|
37282
|
+
const evidenceByAchievement = new Map(
|
|
37283
|
+
achievementEvidence.map((entry) => [entry.achievement, entry])
|
|
37284
|
+
);
|
|
37285
|
+
const checklist = sourceItems.map((achievement, index) => {
|
|
37286
|
+
const displayName = getStringValue(achievement.displayName) ?? getStringValue(achievement.apiName);
|
|
37287
|
+
const evidence = displayName ? evidenceByAchievement.get(displayName) : void 0;
|
|
37288
|
+
const globalPercent = toNumber(achievement.globalPercent);
|
|
37028
37289
|
return {
|
|
37029
|
-
|
|
37030
|
-
|
|
37031
|
-
|
|
37032
|
-
|
|
37033
|
-
|
|
37034
|
-
|
|
37035
|
-
|
|
37036
|
-
|
|
37037
|
-
|
|
37038
|
-
|
|
37039
|
-
|
|
37040
|
-
|
|
37290
|
+
checklistIndex: index + 1,
|
|
37291
|
+
apiName: getStringValue(achievement.apiName),
|
|
37292
|
+
displayName,
|
|
37293
|
+
description: getStringValue(achievement.description),
|
|
37294
|
+
hidden: toBoolean(achievement.hidden) ?? false,
|
|
37295
|
+
globalPercent,
|
|
37296
|
+
rarityBand: classifyRarityBand(globalPercent),
|
|
37297
|
+
icon: getStringValue(achievement.icon),
|
|
37298
|
+
iconGray: getStringValue(achievement.iconGray),
|
|
37299
|
+
guideEvidenceCount: evidence?.evidenceCount ?? 0,
|
|
37300
|
+
guideEvidence: evidence?.evidence ?? [],
|
|
37301
|
+
guideSources: evidence?.sources ?? []
|
|
37041
37302
|
};
|
|
37042
|
-
}
|
|
37043
|
-
const
|
|
37044
|
-
|
|
37045
|
-
|
|
37046
|
-
const
|
|
37047
|
-
|
|
37048
|
-
|
|
37049
|
-
const
|
|
37050
|
-
|
|
37051
|
-
|
|
37052
|
-
const
|
|
37053
|
-
|
|
37054
|
-
|
|
37055
|
-
|
|
37056
|
-
|
|
37057
|
-
|
|
37058
|
-
|
|
37059
|
-
|
|
37060
|
-
historicalLow: lowest,
|
|
37061
|
-
bundledCount: bundled,
|
|
37062
|
-
urls,
|
|
37063
|
-
source: {
|
|
37064
|
-
name: "Augmented Steam",
|
|
37065
|
-
endpoint: AUGMENTED_STEAM_PRICES_ENDPOINT
|
|
37066
|
-
}
|
|
37067
|
-
};
|
|
37303
|
+
});
|
|
37304
|
+
const hidden = checklist.filter(
|
|
37305
|
+
(achievement) => toBoolean(achievement.hidden) === true
|
|
37306
|
+
);
|
|
37307
|
+
const withPercent = checklist.filter(
|
|
37308
|
+
(achievement) => toNumber(achievement.globalPercent) !== void 0
|
|
37309
|
+
);
|
|
37310
|
+
const sortedByRarity = [...withPercent].sort(
|
|
37311
|
+
(left, right) => (toNumber(left.globalPercent) ?? Number.POSITIVE_INFINITY) - (toNumber(right.globalPercent) ?? Number.POSITIVE_INFINITY)
|
|
37312
|
+
);
|
|
37313
|
+
const sortedByCommonness = [...sortedByRarity].reverse();
|
|
37314
|
+
const averageUnlockRate = withPercent.length > 0 ? roundTo(
|
|
37315
|
+
withPercent.reduce(
|
|
37316
|
+
(sum, achievement) => sum + (toNumber(achievement.globalPercent) ?? 0),
|
|
37317
|
+
0
|
|
37318
|
+
) / withPercent.length,
|
|
37319
|
+
2
|
|
37320
|
+
) : null;
|
|
37068
37321
|
return {
|
|
37069
|
-
ok:
|
|
37322
|
+
ok: overview.ok,
|
|
37070
37323
|
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37071
|
-
target:
|
|
37324
|
+
target: {
|
|
37325
|
+
app
|
|
37326
|
+
},
|
|
37072
37327
|
summary: {
|
|
37073
|
-
|
|
37074
|
-
|
|
37075
|
-
|
|
37076
|
-
|
|
37077
|
-
|
|
37078
|
-
|
|
37079
|
-
|
|
37080
|
-
|
|
37081
|
-
|
|
37082
|
-
|
|
37083
|
-
|
|
37084
|
-
|
|
37085
|
-
|
|
37086
|
-
|
|
37328
|
+
source: "official_achievements+steam_guides",
|
|
37329
|
+
totalAchievements: checklist.length,
|
|
37330
|
+
hiddenCount: hidden.length,
|
|
37331
|
+
visibleCount: checklist.length - hidden.length,
|
|
37332
|
+
achievementsWithGuideEvidence: achievementEvidence.length,
|
|
37333
|
+
guideCount: validGuides.length,
|
|
37334
|
+
guideFactCount: guideFacts.length,
|
|
37335
|
+
missableCount: guideFacts.filter((fact) => fact.category === "missable").length,
|
|
37336
|
+
coOpCount: guideFacts.filter((fact) => fact.category === "co_op").length,
|
|
37337
|
+
difficultyCount: guideFacts.filter((fact) => fact.category === "difficulty").length,
|
|
37338
|
+
setupCount: guideFacts.filter((fact) => fact.category === "setup").length,
|
|
37339
|
+
cleanupCount: guideFacts.filter((fact) => fact.category === "cleanup").length,
|
|
37340
|
+
averageUnlockRate,
|
|
37341
|
+
schemaEnriched: toBoolean(overviewSummary?.schemaEnriched) ?? false
|
|
37087
37342
|
},
|
|
37088
|
-
items:
|
|
37343
|
+
items: checklist,
|
|
37089
37344
|
sections: {
|
|
37090
|
-
|
|
37091
|
-
|
|
37092
|
-
|
|
37093
|
-
|
|
37094
|
-
|
|
37095
|
-
|
|
37096
|
-
|
|
37345
|
+
rarest: sortedByRarity.slice(0, input.topCount),
|
|
37346
|
+
mostCommon: sortedByCommonness.slice(0, input.topCount),
|
|
37347
|
+
hidden,
|
|
37348
|
+
guideFacts,
|
|
37349
|
+
achievementEvidence,
|
|
37350
|
+
guideFactCounts: buildGuideFactCounts(guideFacts),
|
|
37351
|
+
rarityBands: buildRarityBandCounts(checklist),
|
|
37352
|
+
sources: validGuides.map((guide) => ({
|
|
37353
|
+
...guide.metadata,
|
|
37354
|
+
mentionCount: guide.mentions.length,
|
|
37355
|
+
factCount: guide.facts.length,
|
|
37356
|
+
score: guide.score
|
|
37357
|
+
}))
|
|
37097
37358
|
},
|
|
37098
37359
|
warnings
|
|
37099
37360
|
};
|
|
37100
37361
|
}
|
|
37101
|
-
async function
|
|
37102
|
-
const
|
|
37103
|
-
|
|
37104
|
-
|
|
37105
|
-
|
|
37106
|
-
|
|
37107
|
-
|
|
37108
|
-
|
|
37109
|
-
|
|
37110
|
-
|
|
37111
|
-
|
|
37362
|
+
async function loadGuideCandidates(runtime2, indexUrls, maxGuides, warnings) {
|
|
37363
|
+
const indexPages = await Promise.all(
|
|
37364
|
+
indexUrls.map(async (url) => {
|
|
37365
|
+
try {
|
|
37366
|
+
return {
|
|
37367
|
+
url,
|
|
37368
|
+
html: await fetchSteamCommunityHtml(url, runtime2.config.timeoutMs)
|
|
37369
|
+
};
|
|
37370
|
+
} catch (error) {
|
|
37371
|
+
warnings.push(
|
|
37372
|
+
`Steam Guides index fetch failed for ${url}: ${error instanceof Error ? error.message : String(error)}`
|
|
37373
|
+
);
|
|
37374
|
+
return null;
|
|
37375
|
+
}
|
|
37376
|
+
})
|
|
37377
|
+
);
|
|
37378
|
+
const candidateMap = /* @__PURE__ */ new Map();
|
|
37379
|
+
for (const page of indexPages) {
|
|
37380
|
+
if (!page) {
|
|
37381
|
+
continue;
|
|
37382
|
+
}
|
|
37383
|
+
for (const candidate of parseGuideCandidates(page.html)) {
|
|
37384
|
+
const existing = candidateMap.get(candidate.guideId);
|
|
37385
|
+
if (!existing || candidate.score > existing.score) {
|
|
37386
|
+
candidateMap.set(candidate.guideId, candidate);
|
|
37387
|
+
}
|
|
37388
|
+
}
|
|
37112
37389
|
}
|
|
37113
|
-
|
|
37114
|
-
|
|
37115
|
-
|
|
37116
|
-
|
|
37117
|
-
|
|
37118
|
-
|
|
37119
|
-
}
|
|
37120
|
-
|
|
37121
|
-
|
|
37122
|
-
|
|
37123
|
-
|
|
37124
|
-
|
|
37125
|
-
|
|
37126
|
-
|
|
37127
|
-
|
|
37128
|
-
|
|
37129
|
-
|
|
37130
|
-
|
|
37131
|
-
|
|
37132
|
-
|
|
37133
|
-
toolName: input.toolName,
|
|
37134
|
-
appid,
|
|
37135
|
-
query,
|
|
37136
|
-
key: input.key,
|
|
37137
|
-
limit: 5,
|
|
37138
|
-
forceRefresh: false,
|
|
37139
|
-
locale: input.language,
|
|
37140
|
-
preferLocalizedName: Boolean(query) || Boolean(input.language)
|
|
37141
|
-
});
|
|
37142
|
-
return {
|
|
37143
|
-
type: "app",
|
|
37144
|
-
id: resolved.appid,
|
|
37145
|
-
resolvedFrom: query ? "query" : "appid",
|
|
37146
|
-
query,
|
|
37147
|
-
appTarget: resolved.target,
|
|
37148
|
-
warnings: resolved.warnings
|
|
37149
|
-
};
|
|
37150
|
-
}
|
|
37151
|
-
async function fetchAugmentedSteamPrices(runtime2, body) {
|
|
37152
|
-
const response = await fetchWithProxy(AUGMENTED_STEAM_PRICES_ENDPOINT, {
|
|
37153
|
-
method: "POST",
|
|
37154
|
-
headers: {
|
|
37155
|
-
accept: "application/json",
|
|
37156
|
-
"content-type": "application/json",
|
|
37157
|
-
"user-agent": "steam-tools-mcp/0.2.0"
|
|
37158
|
-
},
|
|
37159
|
-
body: JSON.stringify(body),
|
|
37160
|
-
signal: AbortSignal.timeout(runtime2.config.timeoutMs)
|
|
37161
|
-
});
|
|
37162
|
-
const text = await response.text();
|
|
37163
|
-
if (!response.ok) {
|
|
37164
|
-
throw new Error(
|
|
37165
|
-
`Augmented Steam prices request failed with ${response.status} ${response.statusText}.`
|
|
37166
|
-
);
|
|
37167
|
-
}
|
|
37168
|
-
try {
|
|
37169
|
-
return JSON.parse(text);
|
|
37170
|
-
} catch (error) {
|
|
37171
|
-
throw new Error(
|
|
37172
|
-
`Augmented Steam prices response was not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
37173
|
-
);
|
|
37174
|
-
}
|
|
37175
|
-
}
|
|
37176
|
-
function normalizePriceNode(value) {
|
|
37177
|
-
if (!value) {
|
|
37178
|
-
return null;
|
|
37179
|
-
}
|
|
37180
|
-
return {
|
|
37181
|
-
shop: normalizeShop(asRecord(value.shop)),
|
|
37182
|
-
price: normalizeMoney(asRecord(value.price)),
|
|
37183
|
-
regular: normalizeMoney(asRecord(value.regular)),
|
|
37184
|
-
cut: toNumber(value.cut),
|
|
37185
|
-
voucher: value.voucher ?? null,
|
|
37186
|
-
flag: value.flag ?? null,
|
|
37187
|
-
drm: Array.isArray(value.drm) ? value.drm : [],
|
|
37188
|
-
platforms: Array.isArray(value.platforms) ? value.platforms.map((entry) => normalizePlatform(asRecord(entry))).filter((entry) => Boolean(entry)) : [],
|
|
37189
|
-
timestamp: getStringValue(value.timestamp),
|
|
37190
|
-
expiry: getStringValue(value.expiry),
|
|
37191
|
-
url: getStringValue(value.url)
|
|
37192
|
-
};
|
|
37193
|
-
}
|
|
37194
|
-
function normalizePriceUrls(value) {
|
|
37195
|
-
if (!value) {
|
|
37196
|
-
return null;
|
|
37197
|
-
}
|
|
37198
|
-
return {
|
|
37199
|
-
info: getStringValue(value.info),
|
|
37200
|
-
history: getStringValue(value.history),
|
|
37201
|
-
bundles: getStringValue(value.bundles)
|
|
37202
|
-
};
|
|
37203
|
-
}
|
|
37204
|
-
function normalizeShop(value) {
|
|
37205
|
-
if (!value) {
|
|
37206
|
-
return null;
|
|
37207
|
-
}
|
|
37208
|
-
return {
|
|
37209
|
-
id: toNumber(value.id),
|
|
37210
|
-
name: getStringValue(value.name)
|
|
37211
|
-
};
|
|
37212
|
-
}
|
|
37213
|
-
function normalizePlatform(value) {
|
|
37214
|
-
if (!value) {
|
|
37215
|
-
return null;
|
|
37216
|
-
}
|
|
37217
|
-
return {
|
|
37218
|
-
id: toNumber(value.id),
|
|
37219
|
-
name: getStringValue(value.name)
|
|
37220
|
-
};
|
|
37221
|
-
}
|
|
37222
|
-
function normalizeMoney(value) {
|
|
37223
|
-
if (!value) {
|
|
37224
|
-
return null;
|
|
37225
|
-
}
|
|
37226
|
-
return {
|
|
37227
|
-
amount: toNumber(value.amount),
|
|
37228
|
-
amountInt: toNumber(value.amountInt),
|
|
37229
|
-
currency: getStringValue(value.currency)
|
|
37230
|
-
};
|
|
37231
|
-
}
|
|
37232
|
-
function parseShopIds(value) {
|
|
37233
|
-
if (value === void 0) {
|
|
37234
|
-
return DEFAULT_SHOP_IDS;
|
|
37235
|
-
}
|
|
37236
|
-
const values = Array.isArray(value) ? value : [value];
|
|
37237
|
-
const shopIds = [...new Set(
|
|
37238
|
-
values.flatMap(
|
|
37239
|
-
(entry) => typeof entry === "string" ? entry.split(/[,\s]+/) : [String(entry)]
|
|
37240
|
-
).map((entry) => normalizeScalarInput(entry)).map((entry) => entry ? Number.parseInt(entry, 10) : Number.NaN).filter((entry) => Number.isFinite(entry) && entry > 0)
|
|
37241
|
-
)];
|
|
37242
|
-
return shopIds.length > 0 ? shopIds : DEFAULT_SHOP_IDS;
|
|
37243
|
-
}
|
|
37244
|
-
function normalizeCountryCode(value) {
|
|
37245
|
-
const normalized = value.trim().toLowerCase();
|
|
37246
|
-
if (!/^[a-z]{2}$/.test(normalized)) {
|
|
37247
|
-
throw new Error("country must be a two-letter ISO 3166-1 country code, such as 'cn' or 'us'.");
|
|
37248
|
-
}
|
|
37249
|
-
return normalized;
|
|
37250
|
-
}
|
|
37251
|
-
function buildPriceToolTarget(target) {
|
|
37252
|
-
return {
|
|
37253
|
-
subject: {
|
|
37254
|
-
type: target.type,
|
|
37255
|
-
id: target.id,
|
|
37256
|
-
resolvedFrom: target.resolvedFrom,
|
|
37257
|
-
query: target.query
|
|
37258
|
-
},
|
|
37259
|
-
...target.appTarget ? { app: target.appTarget } : {}
|
|
37260
|
-
};
|
|
37261
|
-
}
|
|
37262
|
-
function parseNumericId(value, fieldName) {
|
|
37263
|
-
const parsed = Number.parseInt(value, 10);
|
|
37264
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
37265
|
-
throw new Error(`${fieldName} must be a positive integer.`);
|
|
37266
|
-
}
|
|
37267
|
-
return parsed;
|
|
37268
|
-
}
|
|
37269
|
-
|
|
37270
|
-
// src/services/roadmap.ts
|
|
37271
|
-
import { load as load2 } from "cheerio";
|
|
37272
|
-
var STEAM_GUIDE_KEYWORDS = [
|
|
37273
|
-
"achievement",
|
|
37274
|
-
"100%",
|
|
37275
|
-
"all achievements",
|
|
37276
|
-
"roadmap",
|
|
37277
|
-
"walkthrough",
|
|
37278
|
-
"missable",
|
|
37279
|
-
"coop",
|
|
37280
|
-
"co-op"
|
|
37281
|
-
];
|
|
37282
|
-
var PHASE_ORDER = [
|
|
37283
|
-
"preparation",
|
|
37284
|
-
"main_story",
|
|
37285
|
-
"co_op",
|
|
37286
|
-
"challenge",
|
|
37287
|
-
"cleanup"
|
|
37288
|
-
];
|
|
37289
|
-
var PHASE_TITLES = {
|
|
37290
|
-
preparation: "Before You Start",
|
|
37291
|
-
main_story: "Main Story Progress",
|
|
37292
|
-
co_op: "Co-op / Multiplayer",
|
|
37293
|
-
challenge: "Harder Or Rarer Targets",
|
|
37294
|
-
cleanup: "Cleanup"
|
|
37295
|
-
};
|
|
37296
|
-
function isPresent(value) {
|
|
37297
|
-
return value !== null && value !== void 0;
|
|
37298
|
-
}
|
|
37299
|
-
async function buildAchievementRoadmapData(runtime2, input) {
|
|
37300
|
-
const resolved = await runtime2.resolveAppSelection({
|
|
37301
|
-
toolName: input.toolName,
|
|
37302
|
-
appid: input.appid,
|
|
37303
|
-
query: input.query,
|
|
37304
|
-
key: input.key,
|
|
37305
|
-
limit: 5,
|
|
37306
|
-
forceRefresh: false,
|
|
37307
|
-
locale: input.language,
|
|
37308
|
-
preferLocalizedName: Boolean(input.query) || Boolean(input.language)
|
|
37309
|
-
});
|
|
37310
|
-
const achievementOverview = await buildGlobalAchievementOverviewData(runtime2, {
|
|
37311
|
-
toolName: input.toolName,
|
|
37312
|
-
appid: resolved.appid,
|
|
37313
|
-
key: input.key,
|
|
37314
|
-
language: input.language,
|
|
37315
|
-
includeSchemaDetails: true,
|
|
37316
|
-
topCount: 10
|
|
37317
|
-
});
|
|
37318
|
-
const achievementItems = getRecordItems(getNestedValue(achievementOverview, "items"));
|
|
37319
|
-
const achievementMap = buildAchievementMap(achievementItems);
|
|
37320
|
-
const warnings = [...resolved.warnings, ...getWarnings(achievementOverview)];
|
|
37321
|
-
const indexUrls = buildSteamGuideIndexUrls(resolved.appid);
|
|
37322
|
-
const indexPages = await Promise.all(
|
|
37323
|
-
indexUrls.map(async (url) => {
|
|
37324
|
-
try {
|
|
37325
|
-
return {
|
|
37326
|
-
url,
|
|
37327
|
-
html: await fetchSteamCommunityHtml(url, runtime2.config.timeoutMs)
|
|
37328
|
-
};
|
|
37329
|
-
} catch (error) {
|
|
37330
|
-
warnings.push(
|
|
37331
|
-
`Steam Guides index fetch failed for ${url}: ${error instanceof Error ? error.message : String(error)}`
|
|
37332
|
-
);
|
|
37333
|
-
return null;
|
|
37334
|
-
}
|
|
37335
|
-
})
|
|
37336
|
-
);
|
|
37337
|
-
const candidateMap = /* @__PURE__ */ new Map();
|
|
37338
|
-
for (const page of indexPages) {
|
|
37339
|
-
if (!page) {
|
|
37340
|
-
continue;
|
|
37341
|
-
}
|
|
37342
|
-
for (const candidate of parseGuideCandidates(page.html)) {
|
|
37343
|
-
const existing = candidateMap.get(candidate.guideId);
|
|
37344
|
-
if (!existing || candidate.score > existing.score) {
|
|
37345
|
-
candidateMap.set(candidate.guideId, candidate);
|
|
37346
|
-
}
|
|
37347
|
-
}
|
|
37348
|
-
}
|
|
37349
|
-
const selectedGuides = [...candidateMap.values()].sort((left, right) => right.score - left.score).slice(0, input.maxGuides);
|
|
37350
|
-
if (selectedGuides.length === 0) {
|
|
37351
|
-
return {
|
|
37352
|
-
ok: false,
|
|
37353
|
-
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37354
|
-
target: {
|
|
37355
|
-
app: resolved.target
|
|
37356
|
-
},
|
|
37357
|
-
summary: {
|
|
37358
|
-
source: "steam_guides",
|
|
37359
|
-
guideCount: 0,
|
|
37360
|
-
routePhaseCount: 0,
|
|
37361
|
-
missableCount: 0
|
|
37362
|
-
},
|
|
37363
|
-
items: [],
|
|
37364
|
-
sections: {
|
|
37365
|
-
sources: [],
|
|
37366
|
-
missables: [],
|
|
37367
|
-
achievementNotes: []
|
|
37368
|
-
},
|
|
37369
|
-
note: "No Steam Guides candidates were found for this game.",
|
|
37370
|
-
warnings
|
|
37371
|
-
};
|
|
37372
|
-
}
|
|
37373
|
-
const guideAnalyses = await Promise.all(
|
|
37374
|
-
selectedGuides.map(async (guide) => {
|
|
37375
|
-
try {
|
|
37376
|
-
const html = await fetchSteamCommunityHtml(guide.url, runtime2.config.timeoutMs);
|
|
37377
|
-
return analyzeGuidePage(html, guide, achievementMap);
|
|
37378
|
-
} catch (error) {
|
|
37379
|
-
warnings.push(
|
|
37380
|
-
`Steam Guide fetch failed for ${guide.url}: ${error instanceof Error ? error.message : String(error)}`
|
|
37381
|
-
);
|
|
37382
|
-
return null;
|
|
37383
|
-
}
|
|
37384
|
-
})
|
|
37385
|
-
);
|
|
37386
|
-
const validGuides = guideAnalyses.filter(
|
|
37387
|
-
(guide) => Boolean(guide)
|
|
37388
|
-
);
|
|
37389
|
-
const routePhases = buildRoutePhases(validGuides, achievementMap);
|
|
37390
|
-
const missables = dedupeAttentionItems(
|
|
37391
|
-
validGuides.flatMap(
|
|
37392
|
-
(guide) => guide.attention.filter((item) => item.category === "missable")
|
|
37393
|
-
)
|
|
37394
|
-
);
|
|
37395
|
-
const achievementNotes = buildAchievementNotes(validGuides, input.maxAchievementNotes);
|
|
37396
|
-
const guideSummary = buildGuideSummary(validGuides, routePhases, missables);
|
|
37397
|
-
return {
|
|
37398
|
-
ok: true,
|
|
37399
|
-
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37400
|
-
target: {
|
|
37401
|
-
app: resolved.target
|
|
37402
|
-
},
|
|
37403
|
-
summary: {
|
|
37404
|
-
source: "steam_guides",
|
|
37405
|
-
guideCount: validGuides.length,
|
|
37406
|
-
routePhaseCount: routePhases.length,
|
|
37407
|
-
missableCount: missables.length,
|
|
37408
|
-
achievementNoteCount: achievementNotes.length,
|
|
37409
|
-
supportedByOfficialAchievements: achievementMap.length > 0
|
|
37410
|
-
},
|
|
37411
|
-
items: routePhases,
|
|
37412
|
-
sections: {
|
|
37413
|
-
guideSummary,
|
|
37414
|
-
sources: validGuides.map((guide) => ({
|
|
37415
|
-
...guide.metadata,
|
|
37416
|
-
mentionCount: guide.mentions.length,
|
|
37417
|
-
attentionCount: guide.attention.length,
|
|
37418
|
-
score: guide.score
|
|
37419
|
-
})),
|
|
37420
|
-
missables,
|
|
37421
|
-
achievementNotes,
|
|
37422
|
-
officialAchievements: {
|
|
37423
|
-
totalCount: achievementMap.length,
|
|
37424
|
-
rarest: getNestedValue(achievementOverview, "sections", "rarest")
|
|
37425
|
-
}
|
|
37426
|
-
},
|
|
37427
|
-
warnings
|
|
37428
|
-
};
|
|
37429
|
-
}
|
|
37430
|
-
function buildSteamGuideIndexUrls(appid) {
|
|
37431
|
-
return [
|
|
37432
|
-
`https://steamcommunity.com/app/${appid}/guides/?l=english`,
|
|
37433
|
-
`https://steamcommunity.com/app/${appid}/guides/?l=english&searchText=achievement`,
|
|
37434
|
-
`https://steamcommunity.com/app/${appid}/guides/?l=english&searchText=100%25`
|
|
37435
|
-
];
|
|
37436
|
-
}
|
|
37437
|
-
async function fetchSteamCommunityHtml(url, timeoutMs) {
|
|
37438
|
-
const response = await fetchWithProxy(url, {
|
|
37439
|
-
headers: {
|
|
37440
|
-
accept: "text/html,application/xhtml+xml",
|
|
37441
|
-
"accept-language": "en-US,en;q=0.9",
|
|
37442
|
-
"user-agent": "steam-tools-mcp/0.2.0"
|
|
37443
|
-
},
|
|
37444
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
37445
|
-
});
|
|
37446
|
-
if (!response.ok) {
|
|
37447
|
-
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
37390
|
+
return [...candidateMap.values()].sort((left, right) => right.score - left.score).slice(0, maxGuides);
|
|
37391
|
+
}
|
|
37392
|
+
function buildSteamGuideIndexUrls(appid) {
|
|
37393
|
+
return [
|
|
37394
|
+
`https://steamcommunity.com/app/${appid}/guides/?l=english`,
|
|
37395
|
+
`https://steamcommunity.com/app/${appid}/guides/?l=english&searchText=achievement`,
|
|
37396
|
+
`https://steamcommunity.com/app/${appid}/guides/?l=english&searchText=100%25`
|
|
37397
|
+
];
|
|
37398
|
+
}
|
|
37399
|
+
async function fetchSteamCommunityHtml(url, timeoutMs) {
|
|
37400
|
+
const response = await fetchWithProxy(url, {
|
|
37401
|
+
headers: {
|
|
37402
|
+
accept: "text/html,application/xhtml+xml",
|
|
37403
|
+
"accept-language": "en-US,en;q=0.9",
|
|
37404
|
+
"user-agent": PACKAGE_USER_AGENT
|
|
37405
|
+
},
|
|
37406
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
37407
|
+
});
|
|
37408
|
+
if (!response.ok) {
|
|
37409
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
37448
37410
|
}
|
|
37449
37411
|
return response.text();
|
|
37450
37412
|
}
|
|
@@ -37510,9 +37472,6 @@ function scoreGuideCandidate(title, snippet) {
|
|
|
37510
37472
|
if (haystack.includes("definitive")) {
|
|
37511
37473
|
score += 8;
|
|
37512
37474
|
}
|
|
37513
|
-
if (haystack.includes("guide")) {
|
|
37514
|
-
score += 6;
|
|
37515
|
-
}
|
|
37516
37475
|
return score;
|
|
37517
37476
|
}
|
|
37518
37477
|
function analyzeGuidePage(html, candidate, achievementMap) {
|
|
@@ -37520,54 +37479,46 @@ function analyzeGuidePage(html, candidate, achievementMap) {
|
|
|
37520
37479
|
$("script, style, noscript").remove();
|
|
37521
37480
|
$("br").replaceWith("\n");
|
|
37522
37481
|
const lines = $.root().text().split(/\n+/).map((line) => cleanText(line)).filter((line) => line.length > 0);
|
|
37523
|
-
const
|
|
37482
|
+
const metadata2 = extractGuideMetadata(lines, candidate);
|
|
37524
37483
|
const mentions = [];
|
|
37525
|
-
const
|
|
37526
|
-
let currentPhase = "preparation";
|
|
37484
|
+
const facts = [];
|
|
37527
37485
|
for (let index = 0; index < lines.length; index += 1) {
|
|
37528
37486
|
const line = lines[index];
|
|
37529
|
-
const phaseFromLine = detectPhaseKey(line);
|
|
37530
|
-
if (phaseFromLine) {
|
|
37531
|
-
currentPhase = phaseFromLine;
|
|
37532
|
-
}
|
|
37533
37487
|
const matchedAchievements = findAchievementsInLine(line, achievementMap);
|
|
37534
37488
|
for (const achievement of matchedAchievements) {
|
|
37535
37489
|
mentions.push({
|
|
37536
37490
|
achievementName: achievement.name,
|
|
37537
37491
|
globalPercent: achievement.globalPercent,
|
|
37538
37492
|
snippet: buildSnippet(lines, index),
|
|
37539
|
-
phaseKey: currentPhase,
|
|
37540
37493
|
source: {
|
|
37541
|
-
guideId:
|
|
37542
|
-
title:
|
|
37543
|
-
url:
|
|
37494
|
+
guideId: metadata2.guideId,
|
|
37495
|
+
title: metadata2.title,
|
|
37496
|
+
url: metadata2.url
|
|
37544
37497
|
}
|
|
37545
37498
|
});
|
|
37546
37499
|
}
|
|
37547
|
-
const
|
|
37548
|
-
if (!
|
|
37500
|
+
const category = classifyGuideFactCategory(line);
|
|
37501
|
+
if (!category) {
|
|
37549
37502
|
continue;
|
|
37550
37503
|
}
|
|
37551
|
-
|
|
37552
|
-
category
|
|
37504
|
+
facts.push({
|
|
37505
|
+
category,
|
|
37553
37506
|
text: line,
|
|
37554
|
-
phaseKey: attentionCategory === "cleanup" ? "cleanup" : currentPhase,
|
|
37555
37507
|
source: {
|
|
37556
|
-
guideId:
|
|
37557
|
-
title:
|
|
37558
|
-
url:
|
|
37508
|
+
guideId: metadata2.guideId,
|
|
37509
|
+
title: metadata2.title,
|
|
37510
|
+
url: metadata2.url
|
|
37559
37511
|
},
|
|
37560
|
-
relatedAchievements: matchedAchievements.map((achievement) => achievement.name)
|
|
37561
|
-
confidence: matchedAchievements.length > 0 || attentionCategory === "missable" ? "high" : "medium"
|
|
37512
|
+
relatedAchievements: matchedAchievements.map((achievement) => achievement.name)
|
|
37562
37513
|
});
|
|
37563
37514
|
}
|
|
37564
37515
|
const uniqueMentions = dedupeMentions(mentions);
|
|
37516
|
+
const uniqueFacts = dedupeGuideFacts(facts);
|
|
37565
37517
|
return {
|
|
37566
|
-
metadata,
|
|
37518
|
+
metadata: metadata2,
|
|
37567
37519
|
mentions: uniqueMentions,
|
|
37568
|
-
|
|
37569
|
-
|
|
37570
|
-
score: candidate.score + uniqueMentions.length * 2 + attention.length
|
|
37520
|
+
facts: uniqueFacts,
|
|
37521
|
+
score: candidate.score + uniqueMentions.length * 2 + uniqueFacts.length
|
|
37571
37522
|
};
|
|
37572
37523
|
}
|
|
37573
37524
|
function extractGuideMetadata(lines, candidate) {
|
|
@@ -37628,289 +37579,425 @@ function findAchievementsInLine(line, achievementMap) {
|
|
|
37628
37579
|
return tokens.length >= 2 && tokens.every((token) => normalizedLine.includes(token));
|
|
37629
37580
|
});
|
|
37630
37581
|
}
|
|
37631
|
-
function
|
|
37632
|
-
const
|
|
37633
|
-
|
|
37634
|
-
|
|
37635
|
-
|
|
37636
|
-
|
|
37637
|
-
|
|
37638
|
-
|
|
37639
|
-
|
|
37582
|
+
function classifyGuideFactCategory(line) {
|
|
37583
|
+
const normalized = normalizeSearchText(line);
|
|
37584
|
+
if (!normalized || normalized.length < 12) {
|
|
37585
|
+
return null;
|
|
37586
|
+
}
|
|
37587
|
+
if (/missable|do not miss|dont miss|don't miss|before finishing|before ending|last chance|point of no return|cannot go back/.test(
|
|
37588
|
+
normalized
|
|
37589
|
+
)) {
|
|
37590
|
+
return "missable";
|
|
37591
|
+
}
|
|
37592
|
+
if (/co op|coop|multiplayer|friend|partner|another player|online/.test(normalized)) {
|
|
37593
|
+
return "co_op";
|
|
37640
37594
|
}
|
|
37595
|
+
if (/hard|hardest|rarest|practice|difficult|challenge/.test(normalized)) {
|
|
37596
|
+
return "difficulty";
|
|
37597
|
+
}
|
|
37598
|
+
if (/cleanup|replay|chapter select|post game|remaining/.test(normalized)) {
|
|
37599
|
+
return "cleanup";
|
|
37600
|
+
}
|
|
37601
|
+
if (/setup|console|bind|command|config|save file|backup/.test(normalized)) {
|
|
37602
|
+
return "setup";
|
|
37603
|
+
}
|
|
37604
|
+
if (/warning|important|note/.test(normalized)) {
|
|
37605
|
+
return "warning";
|
|
37606
|
+
}
|
|
37607
|
+
return null;
|
|
37608
|
+
}
|
|
37609
|
+
function buildSnippet(lines, index) {
|
|
37610
|
+
return lines.slice(Math.max(0, index - 1), Math.min(lines.length, index + 2)).join(" ").slice(0, 320);
|
|
37611
|
+
}
|
|
37612
|
+
function buildAchievementMap(items) {
|
|
37613
|
+
return items.map((item) => {
|
|
37614
|
+
const name = getStringValue(item.displayName) ?? getStringValue(item.apiName) ?? void 0;
|
|
37615
|
+
if (!name) {
|
|
37616
|
+
return null;
|
|
37617
|
+
}
|
|
37618
|
+
return {
|
|
37619
|
+
apiName: getStringValue(item.apiName),
|
|
37620
|
+
name,
|
|
37621
|
+
normalizedName: normalizeSearchText(name),
|
|
37622
|
+
globalPercent: toNumber(item.globalPercent)
|
|
37623
|
+
};
|
|
37624
|
+
}).filter(isPresent);
|
|
37625
|
+
}
|
|
37626
|
+
function buildAchievementEvidence(guides, maxEvidencePerAchievement) {
|
|
37627
|
+
const evidenceByAchievement = /* @__PURE__ */ new Map();
|
|
37641
37628
|
for (const guide of guides) {
|
|
37642
37629
|
for (const mention of guide.mentions) {
|
|
37643
|
-
const
|
|
37644
|
-
|
|
37645
|
-
|
|
37646
|
-
|
|
37647
|
-
|
|
37648
|
-
|
|
37649
|
-
|
|
37650
|
-
|
|
37651
|
-
|
|
37652
|
-
evidence: mention.snippet
|
|
37653
|
-
});
|
|
37654
|
-
phase.sources.push(mention.source.title);
|
|
37655
|
-
assignedAchievements.add(mention.achievementName);
|
|
37630
|
+
const existing = evidenceByAchievement.get(mention.achievementName) ?? {
|
|
37631
|
+
globalPercent: mention.globalPercent,
|
|
37632
|
+
snippets: [],
|
|
37633
|
+
sources: []
|
|
37634
|
+
};
|
|
37635
|
+
existing.globalPercent = existing.globalPercent ?? mention.globalPercent;
|
|
37636
|
+
existing.snippets.push(mention.snippet);
|
|
37637
|
+
existing.sources.push(mention.source.title);
|
|
37638
|
+
evidenceByAchievement.set(mention.achievementName, existing);
|
|
37656
37639
|
}
|
|
37657
|
-
|
|
37658
|
-
|
|
37659
|
-
|
|
37660
|
-
|
|
37661
|
-
|
|
37662
|
-
|
|
37663
|
-
|
|
37640
|
+
}
|
|
37641
|
+
return [...evidenceByAchievement.entries()].map(([achievement, evidence]) => ({
|
|
37642
|
+
achievement,
|
|
37643
|
+
globalPercent: evidence.globalPercent ?? null,
|
|
37644
|
+
evidenceCount: uniqueStrings(evidence.snippets).length,
|
|
37645
|
+
evidence: uniqueStrings(evidence.snippets).slice(0, maxEvidencePerAchievement),
|
|
37646
|
+
sources: uniqueStrings(evidence.sources)
|
|
37647
|
+
})).sort(
|
|
37648
|
+
(left, right) => (toNumber(left.globalPercent) ?? Number.POSITIVE_INFINITY) - (toNumber(right.globalPercent) ?? Number.POSITIVE_INFINITY)
|
|
37649
|
+
);
|
|
37650
|
+
}
|
|
37651
|
+
function buildGuideFactCounts(facts) {
|
|
37652
|
+
const categories = [
|
|
37653
|
+
"missable",
|
|
37654
|
+
"co_op",
|
|
37655
|
+
"difficulty",
|
|
37656
|
+
"cleanup",
|
|
37657
|
+
"setup",
|
|
37658
|
+
"warning"
|
|
37659
|
+
];
|
|
37660
|
+
return categories.map((category) => ({
|
|
37661
|
+
category,
|
|
37662
|
+
count: facts.filter((fact) => fact.category === category).length
|
|
37663
|
+
}));
|
|
37664
|
+
}
|
|
37665
|
+
function dedupeMentions(mentions) {
|
|
37666
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37667
|
+
return mentions.filter((mention) => {
|
|
37668
|
+
const key = `${mention.achievementName}:${normalizeSearchText(mention.snippet)}`;
|
|
37669
|
+
if (seen.has(key)) {
|
|
37670
|
+
return false;
|
|
37671
|
+
}
|
|
37672
|
+
seen.add(key);
|
|
37673
|
+
return true;
|
|
37674
|
+
});
|
|
37675
|
+
}
|
|
37676
|
+
function dedupeGuideFacts(facts) {
|
|
37677
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37678
|
+
return facts.filter((fact) => {
|
|
37679
|
+
const key = `${fact.category}:${normalizeSearchText(fact.text)}`;
|
|
37680
|
+
if (seen.has(key)) {
|
|
37681
|
+
return false;
|
|
37682
|
+
}
|
|
37683
|
+
seen.add(key);
|
|
37684
|
+
return true;
|
|
37685
|
+
});
|
|
37686
|
+
}
|
|
37687
|
+
function buildRarityBandCounts(checklist) {
|
|
37688
|
+
return [
|
|
37689
|
+
...RARITY_BANDS.map((band) => ({
|
|
37690
|
+
key: band.key,
|
|
37691
|
+
label: band.label,
|
|
37692
|
+
minPercent: band.minPercent,
|
|
37693
|
+
maxPercent: Number.isFinite(band.maxPercent) ? band.maxPercent : null,
|
|
37694
|
+
count: checklist.filter(
|
|
37695
|
+
(achievement) => achievement.rarityBand === band.key
|
|
37696
|
+
).length
|
|
37697
|
+
})),
|
|
37698
|
+
{
|
|
37699
|
+
key: "unknown",
|
|
37700
|
+
label: "Unknown",
|
|
37701
|
+
minPercent: null,
|
|
37702
|
+
maxPercent: null,
|
|
37703
|
+
count: checklist.filter(
|
|
37704
|
+
(achievement) => achievement.rarityBand === "unknown"
|
|
37705
|
+
).length
|
|
37706
|
+
}
|
|
37707
|
+
];
|
|
37708
|
+
}
|
|
37709
|
+
function classifyRarityBand(globalPercent) {
|
|
37710
|
+
if (globalPercent === void 0) {
|
|
37711
|
+
return "unknown";
|
|
37712
|
+
}
|
|
37713
|
+
for (const band of RARITY_BANDS) {
|
|
37714
|
+
if (globalPercent >= band.minPercent && globalPercent < band.maxPercent) {
|
|
37715
|
+
return band.key;
|
|
37664
37716
|
}
|
|
37665
37717
|
}
|
|
37666
|
-
|
|
37667
|
-
|
|
37668
|
-
|
|
37669
|
-
);
|
|
37670
|
-
if (
|
|
37671
|
-
|
|
37672
|
-
|
|
37673
|
-
|
|
37674
|
-
|
|
37675
|
-
|
|
37676
|
-
|
|
37677
|
-
|
|
37678
|
-
|
|
37679
|
-
|
|
37718
|
+
return "unknown";
|
|
37719
|
+
}
|
|
37720
|
+
function parseCount(line) {
|
|
37721
|
+
const match = line.match(/(\d[\d,]*)/);
|
|
37722
|
+
if (!match) {
|
|
37723
|
+
return void 0;
|
|
37724
|
+
}
|
|
37725
|
+
return Number.parseInt(match[1].replace(/,/g, ""), 10);
|
|
37726
|
+
}
|
|
37727
|
+
function extractGuideId(url) {
|
|
37728
|
+
try {
|
|
37729
|
+
const parsed = new URL(url);
|
|
37730
|
+
const guideId = parsed.searchParams.get("id");
|
|
37731
|
+
return guideId ?? void 0;
|
|
37732
|
+
} catch {
|
|
37733
|
+
return void 0;
|
|
37734
|
+
}
|
|
37735
|
+
}
|
|
37736
|
+
function getRecordItems(value) {
|
|
37737
|
+
return Array.isArray(value) ? value.map((entry) => asRecord(entry)).filter((entry) => Boolean(entry)) : [];
|
|
37738
|
+
}
|
|
37739
|
+
function cleanText(value) {
|
|
37740
|
+
return value.replace(/\s+/g, " ").trim();
|
|
37741
|
+
}
|
|
37742
|
+
|
|
37743
|
+
// src/services/prices.ts
|
|
37744
|
+
var AUGMENTED_STEAM_PRICES_ENDPOINT = "https://api.augmentedsteam.com/prices/v2";
|
|
37745
|
+
var DEFAULT_SHOP_IDS = [61];
|
|
37746
|
+
async function buildPriceOverviewData(runtime2, input) {
|
|
37747
|
+
const target = await resolvePriceTarget(runtime2, input);
|
|
37748
|
+
const country = normalizeCountryCode(input.country);
|
|
37749
|
+
const shopIds = parseShopIds(input.shops);
|
|
37750
|
+
const payload = await fetchAugmentedSteamPrices(runtime2, {
|
|
37751
|
+
country,
|
|
37752
|
+
apps: target.type === "app" ? [parseNumericId(target.id, "appid")] : [],
|
|
37753
|
+
subs: target.type === "sub" ? [parseNumericId(target.id, "subid")] : [],
|
|
37754
|
+
bundles: target.type === "bundle" ? [parseNumericId(target.id, "bundleid")] : [],
|
|
37755
|
+
voucher: input.includeVoucher,
|
|
37756
|
+
shops: shopIds
|
|
37757
|
+
});
|
|
37758
|
+
const priceRecord = asRecord(getNestedValue(payload, "prices", `${target.type}/${target.id}`));
|
|
37759
|
+
const warnings = [...target.warnings];
|
|
37760
|
+
if (!priceRecord) {
|
|
37761
|
+
return {
|
|
37762
|
+
ok: false,
|
|
37763
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37764
|
+
target: buildPriceToolTarget(target),
|
|
37765
|
+
summary: {
|
|
37766
|
+
type: target.type,
|
|
37767
|
+
country,
|
|
37768
|
+
source: "augmentedsteam",
|
|
37769
|
+
requestedShopIds: shopIds
|
|
37770
|
+
},
|
|
37771
|
+
items: [],
|
|
37772
|
+
note: `No price data was returned for ${target.type}/${target.id} in country '${country}'.`,
|
|
37773
|
+
warnings
|
|
37774
|
+
};
|
|
37775
|
+
}
|
|
37776
|
+
const current = normalizePriceNode(asRecord(priceRecord.current));
|
|
37777
|
+
const lowest = normalizePriceNode(asRecord(priceRecord.lowest));
|
|
37778
|
+
const urls = normalizePriceUrls(asRecord(priceRecord.urls));
|
|
37779
|
+
const bundled = toNumber(priceRecord.bundled) ?? 0;
|
|
37780
|
+
const currentAmount = toNumber(getNestedValue(current, "price", "amount"));
|
|
37781
|
+
const lowestAmount = toNumber(getNestedValue(lowest, "price", "amount"));
|
|
37782
|
+
const lowestTimestamp = getStringValue(lowest?.timestamp);
|
|
37783
|
+
const historicalLowDate = lowestTimestamp ? new Date(lowestTimestamp).toISOString().slice(0, 10) : null;
|
|
37784
|
+
const currentMatchesHistoricalLow = currentAmount !== void 0 && lowestAmount !== void 0 && currentAmount <= lowestAmount;
|
|
37785
|
+
const item = {
|
|
37786
|
+
type: target.type,
|
|
37787
|
+
id: target.id,
|
|
37788
|
+
historicalLowPrice: getNestedValue(lowest, "price"),
|
|
37789
|
+
historicalLowDate,
|
|
37790
|
+
currentLowestPrice: getNestedValue(current, "price"),
|
|
37791
|
+
currentIsHistoricalLow: currentMatchesHistoricalLow,
|
|
37792
|
+
current,
|
|
37793
|
+
historicalLow: lowest,
|
|
37794
|
+
bundledCount: bundled,
|
|
37795
|
+
urls,
|
|
37796
|
+
source: {
|
|
37797
|
+
name: "Augmented Steam",
|
|
37798
|
+
endpoint: AUGMENTED_STEAM_PRICES_ENDPOINT
|
|
37799
|
+
}
|
|
37800
|
+
};
|
|
37801
|
+
return {
|
|
37802
|
+
ok: true,
|
|
37803
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37804
|
+
target: buildPriceToolTarget(target),
|
|
37805
|
+
summary: {
|
|
37806
|
+
type: target.type,
|
|
37807
|
+
country,
|
|
37808
|
+
source: "augmentedsteam",
|
|
37809
|
+
requestedShopIds: shopIds,
|
|
37810
|
+
hasCurrentPrice: current !== null,
|
|
37811
|
+
hasHistoricalLow: lowest !== null,
|
|
37812
|
+
historicalLowPrice: getNestedValue(lowest, "price"),
|
|
37813
|
+
historicalLowDate,
|
|
37814
|
+
currentLowestPrice: getNestedValue(current, "price"),
|
|
37815
|
+
currentMatchesHistoricalLow,
|
|
37816
|
+
currentIsHistoricalLow: currentMatchesHistoricalLow,
|
|
37817
|
+
currentDiscountPercent: toNumber(current?.cut) ?? null,
|
|
37818
|
+
historicalLowDiscountPercent: toNumber(lowest?.cut) ?? null,
|
|
37819
|
+
bundledCount: bundled
|
|
37820
|
+
},
|
|
37821
|
+
items: [item],
|
|
37822
|
+
sections: {
|
|
37823
|
+
provider: {
|
|
37824
|
+
name: "Augmented Steam",
|
|
37825
|
+
endpoint: AUGMENTED_STEAM_PRICES_ENDPOINT,
|
|
37826
|
+
requestedShopIds: shopIds,
|
|
37827
|
+
steamOnly: shopIds.length === 1 && shopIds[0] === 61
|
|
37828
|
+
},
|
|
37829
|
+
links: urls
|
|
37830
|
+
},
|
|
37831
|
+
warnings
|
|
37832
|
+
};
|
|
37833
|
+
}
|
|
37834
|
+
async function resolvePriceTarget(runtime2, input) {
|
|
37835
|
+
const appid = normalizeScalarInput(input.appid);
|
|
37836
|
+
const subid = normalizeScalarInput(input.subid);
|
|
37837
|
+
const bundleid = normalizeScalarInput(input.bundleid);
|
|
37838
|
+
const query = normalizeScalarInput(input.query);
|
|
37839
|
+
const explicitTargets = [appid, subid, bundleid].filter(Boolean);
|
|
37840
|
+
if (explicitTargets.length > 1) {
|
|
37841
|
+
throw new Error("Provide only one of appid, subid, or bundleid.");
|
|
37842
|
+
}
|
|
37843
|
+
if ((subid || bundleid) && query) {
|
|
37844
|
+
throw new Error("query can only be used with app targets. Use subid or bundleid directly.");
|
|
37680
37845
|
}
|
|
37681
|
-
|
|
37682
|
-
const phase = phases.get(phaseKey);
|
|
37683
|
-
if (!phase) {
|
|
37684
|
-
return null;
|
|
37685
|
-
}
|
|
37686
|
-
const notes = uniqueStrings(phase.notes).slice(0, 6);
|
|
37687
|
-
const achievements = phase.achievements;
|
|
37688
|
-
if (notes.length === 0 && achievements.length === 0) {
|
|
37689
|
-
return null;
|
|
37690
|
-
}
|
|
37846
|
+
if (subid) {
|
|
37691
37847
|
return {
|
|
37692
|
-
|
|
37693
|
-
|
|
37694
|
-
|
|
37695
|
-
|
|
37696
|
-
achievements,
|
|
37697
|
-
notes,
|
|
37698
|
-
sources: uniqueStrings(phase.sources)
|
|
37848
|
+
type: "sub",
|
|
37849
|
+
id: subid,
|
|
37850
|
+
resolvedFrom: "subid",
|
|
37851
|
+
warnings: []
|
|
37699
37852
|
};
|
|
37700
|
-
}).filter(isPresent);
|
|
37701
|
-
}
|
|
37702
|
-
function buildAchievementNotes(guides, maxAchievementNotes) {
|
|
37703
|
-
const byAchievement = /* @__PURE__ */ new Map();
|
|
37704
|
-
for (const guide of guides) {
|
|
37705
|
-
for (const mention of guide.mentions) {
|
|
37706
|
-
const existing = byAchievement.get(mention.achievementName) ?? {
|
|
37707
|
-
snippets: [],
|
|
37708
|
-
phaseKeys: [],
|
|
37709
|
-
sources: [],
|
|
37710
|
-
globalPercent: mention.globalPercent
|
|
37711
|
-
};
|
|
37712
|
-
existing.snippets.push(mention.snippet);
|
|
37713
|
-
existing.phaseKeys.push(mention.phaseKey);
|
|
37714
|
-
existing.sources.push(mention.source.title);
|
|
37715
|
-
existing.globalPercent = existing.globalPercent ?? mention.globalPercent;
|
|
37716
|
-
byAchievement.set(mention.achievementName, existing);
|
|
37717
|
-
}
|
|
37718
|
-
}
|
|
37719
|
-
return [...byAchievement.entries()].map(([achievement, value]) => ({
|
|
37720
|
-
achievement,
|
|
37721
|
-
suggestedPhase: mostCommon(value.phaseKeys),
|
|
37722
|
-
globalPercent: value.globalPercent ?? null,
|
|
37723
|
-
evidence: uniqueStrings(value.snippets).slice(0, 2),
|
|
37724
|
-
sources: uniqueStrings(value.sources)
|
|
37725
|
-
})).sort((left, right) => {
|
|
37726
|
-
const leftGlobal = toNumber(left.globalPercent) ?? -1;
|
|
37727
|
-
const rightGlobal = toNumber(right.globalPercent) ?? -1;
|
|
37728
|
-
return rightGlobal - leftGlobal;
|
|
37729
|
-
}).slice(0, maxAchievementNotes);
|
|
37730
|
-
}
|
|
37731
|
-
function buildGuideSummary(guides, routePhases, missables) {
|
|
37732
|
-
const coOpSignals = guides.flatMap(
|
|
37733
|
-
(guide) => guide.attention.filter((item) => item.category === "co_op")
|
|
37734
|
-
);
|
|
37735
|
-
const difficultySignals = guides.flatMap(
|
|
37736
|
-
(guide) => guide.attention.filter((item) => item.category === "difficulty")
|
|
37737
|
-
);
|
|
37738
|
-
const cleanupSignals = guides.flatMap(
|
|
37739
|
-
(guide) => guide.attention.filter((item) => item.category === "cleanup")
|
|
37740
|
-
);
|
|
37741
|
-
const digest = [];
|
|
37742
|
-
if (coOpSignals.length > 0) {
|
|
37743
|
-
digest.push({
|
|
37744
|
-
topic: "co_op",
|
|
37745
|
-
summary: "Selected Steam Guides indicate that some achievements require co-op, multiplayer, or another player.",
|
|
37746
|
-
evidenceCount: coOpSignals.length,
|
|
37747
|
-
sources: uniqueStrings(coOpSignals.map((item) => item.source.title))
|
|
37748
|
-
});
|
|
37749
|
-
}
|
|
37750
|
-
if (difficultySignals.length > 0) {
|
|
37751
|
-
digest.push({
|
|
37752
|
-
topic: "difficulty",
|
|
37753
|
-
summary: "Selected Steam Guides call out harder or rarer targets that may need extra practice, planning, or setup.",
|
|
37754
|
-
evidenceCount: difficultySignals.length,
|
|
37755
|
-
sources: uniqueStrings(difficultySignals.map((item) => item.source.title))
|
|
37756
|
-
});
|
|
37757
37853
|
}
|
|
37758
|
-
if (
|
|
37759
|
-
|
|
37760
|
-
|
|
37761
|
-
|
|
37762
|
-
|
|
37763
|
-
|
|
37764
|
-
}
|
|
37854
|
+
if (bundleid) {
|
|
37855
|
+
return {
|
|
37856
|
+
type: "bundle",
|
|
37857
|
+
id: bundleid,
|
|
37858
|
+
resolvedFrom: "bundleid",
|
|
37859
|
+
warnings: []
|
|
37860
|
+
};
|
|
37765
37861
|
}
|
|
37766
|
-
if (
|
|
37767
|
-
|
|
37768
|
-
topic: "missables",
|
|
37769
|
-
summary: "The selected Steam Guides contain explicit missable or timing-sensitive warnings.",
|
|
37770
|
-
evidenceCount: missables.length,
|
|
37771
|
-
sources: uniqueStrings(missables.map((item) => item.source.title))
|
|
37772
|
-
});
|
|
37862
|
+
if (!appid && !query) {
|
|
37863
|
+
throw new Error("steam_get_price_overview requires appid, subid, bundleid, or query.");
|
|
37773
37864
|
}
|
|
37774
|
-
|
|
37775
|
-
|
|
37776
|
-
|
|
37777
|
-
|
|
37778
|
-
|
|
37779
|
-
|
|
37780
|
-
|
|
37781
|
-
|
|
37782
|
-
|
|
37783
|
-
seen.add(key);
|
|
37784
|
-
return true;
|
|
37865
|
+
const resolved = await runtime2.resolveAppSelection({
|
|
37866
|
+
toolName: input.toolName,
|
|
37867
|
+
appid,
|
|
37868
|
+
query,
|
|
37869
|
+
key: input.key,
|
|
37870
|
+
limit: 5,
|
|
37871
|
+
forceRefresh: false,
|
|
37872
|
+
locale: input.language,
|
|
37873
|
+
preferLocalizedName: Boolean(query) || Boolean(input.language)
|
|
37785
37874
|
});
|
|
37875
|
+
return {
|
|
37876
|
+
type: "app",
|
|
37877
|
+
id: resolved.appid,
|
|
37878
|
+
resolvedFrom: query ? "query" : "appid",
|
|
37879
|
+
query,
|
|
37880
|
+
appTarget: resolved.target,
|
|
37881
|
+
warnings: resolved.warnings
|
|
37882
|
+
};
|
|
37786
37883
|
}
|
|
37787
|
-
function
|
|
37788
|
-
const
|
|
37789
|
-
|
|
37790
|
-
|
|
37791
|
-
|
|
37792
|
-
|
|
37793
|
-
|
|
37794
|
-
|
|
37795
|
-
|
|
37884
|
+
async function fetchAugmentedSteamPrices(runtime2, body) {
|
|
37885
|
+
const response = await fetchWithProxy(AUGMENTED_STEAM_PRICES_ENDPOINT, {
|
|
37886
|
+
method: "POST",
|
|
37887
|
+
headers: {
|
|
37888
|
+
accept: "application/json",
|
|
37889
|
+
"content-type": "application/json",
|
|
37890
|
+
"user-agent": PACKAGE_USER_AGENT
|
|
37891
|
+
},
|
|
37892
|
+
body: JSON.stringify(body),
|
|
37893
|
+
signal: AbortSignal.timeout(runtime2.config.timeoutMs)
|
|
37796
37894
|
});
|
|
37797
|
-
|
|
37798
|
-
|
|
37799
|
-
|
|
37800
|
-
|
|
37801
|
-
|
|
37802
|
-
}
|
|
37803
|
-
if (normalized.includes("before you start") || normalized === "overview" || normalized === "notes" || normalized.includes("setup")) {
|
|
37804
|
-
return "preparation";
|
|
37805
|
-
}
|
|
37806
|
-
if (normalized.includes("singleplayer") || normalized.includes("campaign") || normalized.includes("main story") || normalized.includes("story")) {
|
|
37807
|
-
return "main_story";
|
|
37808
|
-
}
|
|
37809
|
-
if (normalized.includes("co op") || normalized.includes("coop") || normalized.includes("multiplayer")) {
|
|
37810
|
-
return "co_op";
|
|
37811
|
-
}
|
|
37812
|
-
if (normalized.includes("challenge") || normalized.includes("hard") || normalized.includes("rarest")) {
|
|
37813
|
-
return "challenge";
|
|
37895
|
+
const text = await response.text();
|
|
37896
|
+
if (!response.ok) {
|
|
37897
|
+
throw new Error(
|
|
37898
|
+
`Augmented Steam prices request failed with ${response.status} ${response.statusText}.`
|
|
37899
|
+
);
|
|
37814
37900
|
}
|
|
37815
|
-
|
|
37816
|
-
return
|
|
37901
|
+
try {
|
|
37902
|
+
return JSON.parse(text);
|
|
37903
|
+
} catch (error) {
|
|
37904
|
+
throw new Error(
|
|
37905
|
+
`Augmented Steam prices response was not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
37906
|
+
);
|
|
37817
37907
|
}
|
|
37818
|
-
return null;
|
|
37819
37908
|
}
|
|
37820
|
-
function
|
|
37821
|
-
|
|
37822
|
-
if (!normalized || normalized.length < 12) {
|
|
37909
|
+
function normalizePriceNode(value) {
|
|
37910
|
+
if (!value) {
|
|
37823
37911
|
return null;
|
|
37824
37912
|
}
|
|
37825
|
-
|
|
37826
|
-
|
|
37827
|
-
|
|
37828
|
-
|
|
37829
|
-
|
|
37830
|
-
|
|
37831
|
-
|
|
37832
|
-
|
|
37833
|
-
|
|
37834
|
-
|
|
37835
|
-
|
|
37836
|
-
|
|
37837
|
-
|
|
37838
|
-
}
|
|
37839
|
-
if (/setup|console|bind|command|config|save file|backup/.test(normalized)) {
|
|
37840
|
-
return "setup";
|
|
37841
|
-
}
|
|
37842
|
-
if (/warning|important|note/.test(normalized)) {
|
|
37843
|
-
return "warning";
|
|
37844
|
-
}
|
|
37845
|
-
return null;
|
|
37846
|
-
}
|
|
37847
|
-
function buildSnippet(lines, index) {
|
|
37848
|
-
return lines.slice(Math.max(0, index - 1), Math.min(lines.length, index + 2)).join(" ").slice(0, 320);
|
|
37849
|
-
}
|
|
37850
|
-
function buildAchievementMap(items) {
|
|
37851
|
-
return items.map((item) => {
|
|
37852
|
-
const name = getStringValue(item.displayName) ?? getStringValue(item.apiName) ?? void 0;
|
|
37853
|
-
if (!name) {
|
|
37854
|
-
return null;
|
|
37855
|
-
}
|
|
37856
|
-
return {
|
|
37857
|
-
name,
|
|
37858
|
-
normalizedName: normalizeSearchText(name),
|
|
37859
|
-
globalPercent: toNumber(item.globalPercent)
|
|
37860
|
-
};
|
|
37861
|
-
}).filter(isPresent);
|
|
37913
|
+
return {
|
|
37914
|
+
shop: normalizeShop(asRecord(value.shop)),
|
|
37915
|
+
price: normalizeMoney(asRecord(value.price)),
|
|
37916
|
+
regular: normalizeMoney(asRecord(value.regular)),
|
|
37917
|
+
cut: toNumber(value.cut),
|
|
37918
|
+
voucher: value.voucher ?? null,
|
|
37919
|
+
flag: value.flag ?? null,
|
|
37920
|
+
drm: Array.isArray(value.drm) ? value.drm : [],
|
|
37921
|
+
platforms: Array.isArray(value.platforms) ? value.platforms.map((entry) => normalizePlatform(asRecord(entry))).filter((entry) => Boolean(entry)) : [],
|
|
37922
|
+
timestamp: getStringValue(value.timestamp),
|
|
37923
|
+
expiry: getStringValue(value.expiry),
|
|
37924
|
+
url: getStringValue(value.url)
|
|
37925
|
+
};
|
|
37862
37926
|
}
|
|
37863
|
-
function
|
|
37864
|
-
|
|
37865
|
-
|
|
37866
|
-
return void 0;
|
|
37927
|
+
function normalizePriceUrls(value) {
|
|
37928
|
+
if (!value) {
|
|
37929
|
+
return null;
|
|
37867
37930
|
}
|
|
37868
|
-
return
|
|
37931
|
+
return {
|
|
37932
|
+
info: getStringValue(value.info),
|
|
37933
|
+
history: getStringValue(value.history),
|
|
37934
|
+
bundles: getStringValue(value.bundles)
|
|
37935
|
+
};
|
|
37869
37936
|
}
|
|
37870
|
-
function
|
|
37871
|
-
|
|
37872
|
-
|
|
37873
|
-
const guideId = parsed.searchParams.get("id");
|
|
37874
|
-
return guideId ?? void 0;
|
|
37875
|
-
} catch {
|
|
37876
|
-
return void 0;
|
|
37937
|
+
function normalizeShop(value) {
|
|
37938
|
+
if (!value) {
|
|
37939
|
+
return null;
|
|
37877
37940
|
}
|
|
37941
|
+
return {
|
|
37942
|
+
id: toNumber(value.id),
|
|
37943
|
+
name: getStringValue(value.name)
|
|
37944
|
+
};
|
|
37878
37945
|
}
|
|
37879
|
-
function
|
|
37880
|
-
|
|
37881
|
-
|
|
37882
|
-
return `Use this phase to capture setup notes and pre-run warnings before starting. (${achievementCount} named achievements, ${noteCount} notes)`;
|
|
37883
|
-
case "main_story":
|
|
37884
|
-
return `Prioritize the achievements the selected Steam Guides place alongside normal story or campaign progress. (${achievementCount} named achievements, ${noteCount} notes)`;
|
|
37885
|
-
case "co_op":
|
|
37886
|
-
return `Set aside the achievements the selected Steam Guides associate with co-op, multiplayer, or another player. (${achievementCount} named achievements, ${noteCount} notes)`;
|
|
37887
|
-
case "challenge":
|
|
37888
|
-
return `Leave the rarer or harder targets for a focused pass once the easier progression is done. (${achievementCount} named achievements, ${noteCount} notes)`;
|
|
37889
|
-
case "cleanup":
|
|
37890
|
-
return `Finish anything not clearly placed by the guides in a final cleanup pass. (${achievementCount} named achievements, ${noteCount} notes)`;
|
|
37891
|
-
default:
|
|
37892
|
-
return `${achievementCount} achievements and ${noteCount} notes`;
|
|
37946
|
+
function normalizePlatform(value) {
|
|
37947
|
+
if (!value) {
|
|
37948
|
+
return null;
|
|
37893
37949
|
}
|
|
37950
|
+
return {
|
|
37951
|
+
id: toNumber(value.id),
|
|
37952
|
+
name: getStringValue(value.name)
|
|
37953
|
+
};
|
|
37894
37954
|
}
|
|
37895
|
-
function
|
|
37896
|
-
if (
|
|
37955
|
+
function normalizeMoney(value) {
|
|
37956
|
+
if (!value) {
|
|
37897
37957
|
return null;
|
|
37898
37958
|
}
|
|
37899
|
-
|
|
37900
|
-
|
|
37901
|
-
|
|
37959
|
+
return {
|
|
37960
|
+
amount: toNumber(value.amount),
|
|
37961
|
+
amountInt: toNumber(value.amountInt),
|
|
37962
|
+
currency: getStringValue(value.currency)
|
|
37963
|
+
};
|
|
37964
|
+
}
|
|
37965
|
+
function parseShopIds(value) {
|
|
37966
|
+
if (value === void 0) {
|
|
37967
|
+
return DEFAULT_SHOP_IDS;
|
|
37902
37968
|
}
|
|
37903
|
-
|
|
37969
|
+
const values = Array.isArray(value) ? value : [value];
|
|
37970
|
+
const shopIds = [...new Set(
|
|
37971
|
+
values.flatMap(
|
|
37972
|
+
(entry) => typeof entry === "string" ? entry.split(/[,\s]+/) : [String(entry)]
|
|
37973
|
+
).map((entry) => normalizeScalarInput(entry)).map((entry) => entry ? Number.parseInt(entry, 10) : Number.NaN).filter((entry) => Number.isFinite(entry) && entry > 0)
|
|
37974
|
+
)];
|
|
37975
|
+
return shopIds.length > 0 ? shopIds : DEFAULT_SHOP_IDS;
|
|
37904
37976
|
}
|
|
37905
|
-
function
|
|
37906
|
-
const
|
|
37907
|
-
|
|
37977
|
+
function normalizeCountryCode(value) {
|
|
37978
|
+
const normalized = value.trim().toLowerCase();
|
|
37979
|
+
if (!/^[a-z]{2}$/.test(normalized)) {
|
|
37980
|
+
throw new Error("country must be a two-letter ISO 3166-1 country code, such as 'cn' or 'us'.");
|
|
37981
|
+
}
|
|
37982
|
+
return normalized;
|
|
37908
37983
|
}
|
|
37909
|
-
function
|
|
37910
|
-
return
|
|
37984
|
+
function buildPriceToolTarget(target) {
|
|
37985
|
+
return {
|
|
37986
|
+
subject: {
|
|
37987
|
+
type: target.type,
|
|
37988
|
+
id: target.id,
|
|
37989
|
+
resolvedFrom: target.resolvedFrom,
|
|
37990
|
+
query: target.query
|
|
37991
|
+
},
|
|
37992
|
+
...target.appTarget ? { app: target.appTarget } : {}
|
|
37993
|
+
};
|
|
37911
37994
|
}
|
|
37912
|
-
function
|
|
37913
|
-
|
|
37995
|
+
function parseNumericId(value, fieldName) {
|
|
37996
|
+
const parsed = Number.parseInt(value, 10);
|
|
37997
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
37998
|
+
throw new Error(`${fieldName} must be a positive integer.`);
|
|
37999
|
+
}
|
|
38000
|
+
return parsed;
|
|
37914
38001
|
}
|
|
37915
38002
|
|
|
37916
38003
|
// src/tools/register-steam-tool.ts
|
|
@@ -38064,7 +38151,7 @@ function registerAppTools(server, runtime2) {
|
|
|
38064
38151
|
"steam_get_price_overview",
|
|
38065
38152
|
{
|
|
38066
38153
|
title: "\u4EF7\u683C\u4E0E\u53F2\u4F4E",
|
|
38067
|
-
description: "\u67E5\u770B app\u3001sub \u6216 bundle \u7684\u5F53\u524D\u6700\u4F4E\u4EF7\u3001\u5386\u53F2\u6700\u4F4E\u4EF7\u3001\u53F2\u4F4E\u65E5\u671F\uFF0C\u4EE5\u53CA\u5F53\u524D\u662F\u5426\u7B49\u4E8E\u53F2\u4F4E\u3002",
|
|
38154
|
+
description: "\u516C\u5171\u4EF7\u683C\u4E13\u9879\u89C6\u56FE\uFF0C\u67E5\u770B app\u3001sub \u6216 bundle \u7684\u5F53\u524D\u6700\u4F4E\u4EF7\u3001\u5386\u53F2\u6700\u4F4E\u4EF7\u3001\u53F2\u4F4E\u65E5\u671F\uFF0C\u4EE5\u53CA\u5F53\u524D\u662F\u5426\u7B49\u4E8E\u53F2\u4F4E\u3002",
|
|
38068
38155
|
inputSchema: {
|
|
38069
38156
|
appid: z2.union([z2.string(), z2.number()]).optional().describe("Steam AppID\u3002\u4E0E subid\u3001bundleid\u3001query \u56DB\u9009\u4E00\u3002"),
|
|
38070
38157
|
subid: z2.union([z2.string(), z2.number()]).optional().describe("Steam Package/Sub ID\u3002\u4E0E appid\u3001bundleid\u3001query \u56DB\u9009\u4E00\u3002"),
|
|
@@ -38113,15 +38200,18 @@ function registerAppTools(server, runtime2) {
|
|
|
38113
38200
|
runtime2,
|
|
38114
38201
|
"steam_get_achievement_roadmap",
|
|
38115
38202
|
{
|
|
38116
|
-
title: "\u6210\u5C31\
|
|
38117
|
-
description: "\
|
|
38203
|
+
title: "\u5168\u6210\u5C31\u653B\u7565",
|
|
38204
|
+
description: "\u516C\u5171\u5355\u6E38\u620F\u653B\u7565\u4E8B\u5B9E\u89C6\u56FE\uFF0C\u6574\u5408\u5B98\u65B9\u6210\u5C31\u6E05\u5355\u548C Steam \u6307\u5357\u4E2D\u7684\u53EF\u8FFD\u6EAF\u4E8B\u5B9E\uFF0C\u4F8B\u5982 missable\u3001co-op \u548C\u6761\u4EF6\u8BF4\u660E\u3002",
|
|
38118
38205
|
inputSchema: {
|
|
38119
38206
|
appid: z2.union([z2.string(), z2.number()]).optional().describe("Steam AppID\u3002\u4E0E query \u4E8C\u9009\u4E00\u3002"),
|
|
38120
38207
|
query: z2.union([z2.string(), z2.number()]).optional().describe("\u6E38\u620F\u540D\u6216 AppID\uFF0C\u652F\u6301\u76F4\u63A5\u8F93\u5165\u4E2D\u6587\u540D\u3002\u4E0E appid \u4E8C\u9009\u4E00\u3002"),
|
|
38121
|
-
key: z2.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\uFF1B\
|
|
38208
|
+
key: z2.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\uFF1B\u8865\u5168\u5B98\u65B9\u6210\u5C31 schema \u65F6\u53EF\u80FD\u9700\u8981\u3002"),
|
|
38122
38209
|
language: z2.string().optional().describe("\u53EF\u9009\u8BED\u8A00\u4EE3\u7801\uFF0C\u4F8B\u5982 schinese \u6216 english\u3002"),
|
|
38123
|
-
|
|
38124
|
-
|
|
38210
|
+
includeSchemaDetails: z2.boolean().optional().describe("\u662F\u5426\u8865\u5145\u5B98\u65B9\u6210\u5C31 schema \u7EC6\u8282\uFF0C\u9ED8\u8BA4 true\u3002"),
|
|
38211
|
+
maxGuides: z2.number().int().min(1).max(8).optional().describe("\u6700\u591A\u6293\u53D6\u591A\u5C11\u7BC7 Steam \u6307\u5357\uFF0C\u9ED8\u8BA4 3\u3002"),
|
|
38212
|
+
maxGuideFacts: z2.number().int().min(1).max(50).optional().describe("\u6700\u591A\u8FD4\u56DE\u591A\u5C11\u6761\u6307\u5357\u4E8B\u5B9E\uFF0C\u9ED8\u8BA4 20\u3002"),
|
|
38213
|
+
maxEvidencePerAchievement: z2.number().int().min(1).max(5).optional().describe("\u6BCF\u4E2A\u6210\u5C31\u6700\u591A\u4FDD\u7559\u591A\u5C11\u6761\u6307\u5357\u8BC1\u636E\uFF0C\u9ED8\u8BA4 2\u3002"),
|
|
38214
|
+
topCount: z2.number().int().min(1).max(50).optional().describe("\u6700\u7A00\u6709\u548C\u6700\u5E38\u89C1\u6210\u5C31\u5404\u8FD4\u56DE\u591A\u5C11\u6761\uFF0C\u9ED8\u8BA4 10\u3002")
|
|
38125
38215
|
},
|
|
38126
38216
|
annotations: {
|
|
38127
38217
|
readOnlyHint: true,
|
|
@@ -38133,16 +38223,22 @@ function registerAppTools(server, runtime2) {
|
|
|
38133
38223
|
query,
|
|
38134
38224
|
key,
|
|
38135
38225
|
language,
|
|
38226
|
+
includeSchemaDetails = true,
|
|
38136
38227
|
maxGuides = 3,
|
|
38137
|
-
|
|
38138
|
-
|
|
38228
|
+
maxGuideFacts = 20,
|
|
38229
|
+
maxEvidencePerAchievement = 2,
|
|
38230
|
+
topCount = 10
|
|
38231
|
+
}) => buildAchievementGuideData(runtime2, {
|
|
38139
38232
|
toolName: "steam_get_achievement_roadmap",
|
|
38140
38233
|
appid,
|
|
38141
38234
|
query,
|
|
38142
38235
|
key,
|
|
38143
38236
|
language,
|
|
38237
|
+
includeSchemaDetails,
|
|
38144
38238
|
maxGuides,
|
|
38145
|
-
|
|
38239
|
+
maxGuideFacts,
|
|
38240
|
+
maxEvidencePerAchievement,
|
|
38241
|
+
topCount
|
|
38146
38242
|
})
|
|
38147
38243
|
);
|
|
38148
38244
|
registerSteamTool(
|
|
@@ -38151,7 +38247,7 @@ function registerAppTools(server, runtime2) {
|
|
|
38151
38247
|
"steam_get_global_achievement_overview",
|
|
38152
38248
|
{
|
|
38153
38249
|
title: "\u5168\u5C40\u6210\u5C31\u603B\u89C8",
|
|
38154
|
-
description: "\u67E5\u770B\u67D0\u4E2A\u6E38\u620F\u7684\u5168\u5C40\u6210\u5C31\u5B8C\u6210\u7387\uFF0C\u5E76\u53EF\u9009\u8865\u5145 schema \u7EC6\u8282\u3002",
|
|
38250
|
+
description: "\u516C\u5171\u5355\u6E38\u620F\u4E13\u9879\u89C6\u56FE\uFF0C\u67E5\u770B\u67D0\u4E2A\u6E38\u620F\u7684\u5168\u5C40\u6210\u5C31\u5B8C\u6210\u7387\uFF0C\u5E76\u53EF\u9009\u8865\u5145 schema \u7EC6\u8282\u3002",
|
|
38155
38251
|
inputSchema: {
|
|
38156
38252
|
appid: z2.union([z2.string(), z2.number()]).optional().describe("Steam AppID\u3002\u4E0E query \u4E8C\u9009\u4E00\u3002"),
|
|
38157
38253
|
query: z2.union([z2.string(), z2.number()]).optional().describe("\u6E38\u620F\u540D\u6216 AppID\uFF0C\u652F\u6301\u76F4\u63A5\u8F93\u5165\u4E2D\u6587\u540D\u3002\u4E0E appid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -38250,7 +38346,7 @@ function buildDefaultPlayerTarget(identity) {
|
|
|
38250
38346
|
}
|
|
38251
38347
|
};
|
|
38252
38348
|
}
|
|
38253
|
-
function
|
|
38349
|
+
function getWarnings(payload) {
|
|
38254
38350
|
const warnings = getNestedValue(payload, "warnings");
|
|
38255
38351
|
return Array.isArray(warnings) ? warnings : [];
|
|
38256
38352
|
}
|
|
@@ -38487,7 +38583,7 @@ async function buildFriendActivityData(runtime2, input) {
|
|
|
38487
38583
|
sections: {
|
|
38488
38584
|
profile: getNestedValue(friendsData, "sections", "profile")
|
|
38489
38585
|
},
|
|
38490
|
-
warnings:
|
|
38586
|
+
warnings: getWarnings(friendsData)
|
|
38491
38587
|
};
|
|
38492
38588
|
}
|
|
38493
38589
|
async function buildFriendNetworkData(runtime2, input) {
|
|
@@ -38556,7 +38652,7 @@ async function buildFriendNetworkData(runtime2, input) {
|
|
|
38556
38652
|
},
|
|
38557
38653
|
graph
|
|
38558
38654
|
},
|
|
38559
|
-
warnings:
|
|
38655
|
+
warnings: getWarnings(friendsData)
|
|
38560
38656
|
};
|
|
38561
38657
|
}
|
|
38562
38658
|
|
|
@@ -38615,8 +38711,8 @@ async function buildGameSnapshotData(runtime2, input) {
|
|
|
38615
38711
|
const warnings = [
|
|
38616
38712
|
...resolved.warnings,
|
|
38617
38713
|
...runtime2.collectWarnings([playerSummaryCall, ownedGamesCall]),
|
|
38618
|
-
...
|
|
38619
|
-
...
|
|
38714
|
+
...getWarnings(achievementOverview),
|
|
38715
|
+
...getWarnings(newsOverview)
|
|
38620
38716
|
];
|
|
38621
38717
|
return {
|
|
38622
38718
|
ok: true,
|
|
@@ -38747,7 +38843,7 @@ async function buildGameFeedData(runtime2, input) {
|
|
|
38747
38843
|
currentPlayers: getNestedValue(newsOverview, "summary", "currentPlayers"),
|
|
38748
38844
|
ownedContext: ownedContextMap.get(appid) ?? null,
|
|
38749
38845
|
items: newsItems,
|
|
38750
|
-
warnings:
|
|
38846
|
+
warnings: getWarnings(newsOverview)
|
|
38751
38847
|
};
|
|
38752
38848
|
})
|
|
38753
38849
|
);
|
|
@@ -38886,7 +38982,7 @@ async function buildBacklogCandidatesData(runtime2, input) {
|
|
|
38886
38982
|
},
|
|
38887
38983
|
warnings: [
|
|
38888
38984
|
...runtime2.collectWarnings([playerSummaryCall, ownedGamesCall]),
|
|
38889
|
-
...shortlist.flatMap((candidate) =>
|
|
38985
|
+
...shortlist.flatMap((candidate) => getWarnings(candidate))
|
|
38890
38986
|
]
|
|
38891
38987
|
};
|
|
38892
38988
|
}
|
|
@@ -38981,7 +39077,7 @@ async function buildAchievementHuntData(runtime2, input) {
|
|
|
38981
39077
|
getNestedValue(overview, "sections", "recentlyUnlocked")
|
|
38982
39078
|
),
|
|
38983
39079
|
easiestRemaining,
|
|
38984
|
-
warnings:
|
|
39080
|
+
warnings: getWarnings(overview)
|
|
38985
39081
|
};
|
|
38986
39082
|
} catch (error) {
|
|
38987
39083
|
return {
|
|
@@ -39203,7 +39299,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39203
39299
|
"steam_me_profile",
|
|
39204
39300
|
{
|
|
39205
39301
|
title: "\u6211\u7684\u8D44\u6599",
|
|
39206
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39302
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E3B\u5165\u53E3\uFF0C\u67E5\u770B\u6211\u7684 Steam \u8D44\u6599\u603B\u89C8\u3002",
|
|
39207
39303
|
inputSchema: {
|
|
39208
39304
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39209
39305
|
includeRecentlyPlayed: z3.boolean().optional().describe("\u662F\u5426\u5305\u542B\u6700\u8FD1\u6E38\u73A9\uFF0C\u9ED8\u8BA4 true\u3002"),
|
|
@@ -39230,7 +39326,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39230
39326
|
"steam_me_library",
|
|
39231
39327
|
{
|
|
39232
39328
|
title: "\u6211\u7684\u6E38\u620F\u5E93",
|
|
39233
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39329
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E3B\u5165\u53E3\uFF0C\u67E5\u770B\u6211\u7684\u6E38\u620F\u5E93\u603B\u89C8\u3002",
|
|
39234
39330
|
inputSchema: {
|
|
39235
39331
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39236
39332
|
includeAppInfo: z3.boolean().optional().describe("\u662F\u5426\u5305\u542B\u6E38\u620F\u540D\u79F0\u548C\u56FE\u6807\uFF0C\u9ED8\u8BA4 true\u3002"),
|
|
@@ -39270,7 +39366,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39270
39366
|
"steam_me_recently_played",
|
|
39271
39367
|
{
|
|
39272
39368
|
title: "\u6211\u7684\u6700\u8FD1\u6E38\u73A9",
|
|
39273
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\u5FEB\u6377\u5165\u53E3\uFF0C\
|
|
39369
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u5FEB\u6377\u5165\u53E3\uFF0C\u53EA\u770B\u6700\u8FD1\u6E38\u73A9\u7684\u6E38\u620F\u3002",
|
|
39274
39370
|
inputSchema: {
|
|
39275
39371
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39276
39372
|
count: z3.number().int().min(1).max(20).optional().describe("\u6700\u8FD1\u6E38\u73A9\u6E38\u620F\u8FD4\u56DE\u6570\u91CF\uFF0C\u9ED8\u8BA4 10\u3002")
|
|
@@ -39295,7 +39391,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39295
39391
|
"steam_me_badges",
|
|
39296
39392
|
{
|
|
39297
39393
|
title: "\u6211\u7684\u5FBD\u7AE0",
|
|
39298
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\u5FEB\u6377\u5165\u53E3\uFF0C\
|
|
39394
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u5FEB\u6377\u5165\u53E3\uFF0C\u53EA\u770B\u6211\u7684\u7B49\u7EA7\u548C\u5FBD\u7AE0\u4FE1\u606F\u3002",
|
|
39299
39395
|
inputSchema: {
|
|
39300
39396
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002")
|
|
39301
39397
|
},
|
|
@@ -39318,7 +39414,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39318
39414
|
"steam_me_game_achievements",
|
|
39319
39415
|
{
|
|
39320
39416
|
title: "\u6211\u7684\u6E38\u620F\u6210\u5C31",
|
|
39321
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39417
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u5355\u6E38\u620F\u4E13\u9879\u89C6\u56FE\uFF0C\u67E5\u770B\u6211\u5728\u67D0\u4E2A\u6E38\u620F\u91CC\u7684\u6210\u5C31\u548C\u5B8C\u6210\u7387\u3002",
|
|
39322
39418
|
inputSchema: {
|
|
39323
39419
|
appid: z3.union([z3.string(), z3.number()]).optional().describe("Steam AppID\u3002\u4E0E query \u4E8C\u9009\u4E00\u3002"),
|
|
39324
39420
|
query: z3.union([z3.string(), z3.number()]).optional().describe("\u6E38\u620F\u540D\u6216 AppID\uFF0C\u652F\u6301\u76F4\u63A5\u8F93\u5165\u4E2D\u6587\u540D\u3002\u4E0E appid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -39358,7 +39454,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39358
39454
|
"steam_me_friends",
|
|
39359
39455
|
{
|
|
39360
39456
|
title: "\u597D\u53CB\u5217\u8868",
|
|
39361
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39457
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E13\u9879\u89C6\u56FE\uFF0C\u67E5\u770B\u597D\u53CB\u5217\u8868\uFF0C\u53EF\u9009\u8865\u5145\u8D44\u6599\u548C\u5C01\u7981\u4FE1\u606F\u3002",
|
|
39362
39458
|
inputSchema: {
|
|
39363
39459
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39364
39460
|
relationship: z3.string().optional().describe("\u597D\u53CB\u5173\u7CFB\u8FC7\u6EE4\u6761\u4EF6\uFF0C\u9ED8\u8BA4 friend\u3002"),
|
|
@@ -39395,7 +39491,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39395
39491
|
"steam_me_friend_activity",
|
|
39396
39492
|
{
|
|
39397
39493
|
title: "\u597D\u53CB\u5728\u7EBF\u52A8\u6001",
|
|
39398
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39494
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E13\u9879\u89C6\u56FE\uFF0C\u67E5\u770B\u54EA\u4E9B\u597D\u53CB\u5728\u7EBF\u3001\u5728\u73A9\u6E38\u620F\u6216\u6700\u8FD1\u6D3B\u8DC3\u3002",
|
|
39399
39495
|
inputSchema: {
|
|
39400
39496
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39401
39497
|
limit: z3.number().int().min(1).max(500).optional().describe("\u6700\u591A\u68C0\u67E5\u591A\u5C11\u4F4D\u597D\u53CB\uFF0C\u9ED8\u8BA4 100\u3002"),
|
|
@@ -39424,7 +39520,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39424
39520
|
"steam_me_friend_network",
|
|
39425
39521
|
{
|
|
39426
39522
|
title: "\u597D\u53CB\u5173\u7CFB\u56FE\u8C31",
|
|
39427
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39523
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E13\u9879\u89C6\u56FE\uFF0C\u751F\u6210\u597D\u53CB\u5173\u7CFB\u548C\u6D3B\u52A8\u5206\u7EC4\u89C6\u56FE\u3002",
|
|
39428
39524
|
inputSchema: {
|
|
39429
39525
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39430
39526
|
limit: z3.number().int().min(1).max(500).optional().describe("\u6700\u591A\u68C0\u67E5\u591A\u5C11\u4F4D\u597D\u53CB\uFF0C\u9ED8\u8BA4 150\u3002"),
|
|
@@ -39465,7 +39561,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39465
39561
|
"steam_me_bans",
|
|
39466
39562
|
{
|
|
39467
39563
|
title: "\u6211\u7684\u5C01\u7981\u6458\u8981",
|
|
39468
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\u5FEB\u6377\u5165\u53E3\uFF0C\
|
|
39564
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u5FEB\u6377\u5165\u53E3\uFF0C\u53EA\u770B\u6211\u7684\u5C01\u7981\u72B6\u6001\u3002",
|
|
39469
39565
|
inputSchema: {
|
|
39470
39566
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002")
|
|
39471
39567
|
},
|
|
@@ -39488,7 +39584,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39488
39584
|
"steam_me_library_compare",
|
|
39489
39585
|
{
|
|
39490
39586
|
title: "\u6211\u7684\u5E93\u5BF9\u6BD4",
|
|
39491
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39587
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E13\u9879\u89C6\u56FE\uFF0C\u628A\u6211\u7684\u5E93\u548C\u53E6\u4E00\u4F4D\u73A9\u5BB6\u505A\u5BF9\u6BD4\u3002",
|
|
39492
39588
|
inputSchema: {
|
|
39493
39589
|
steamid: z3.union([z3.string(), z3.number()]).optional().describe("\u5BF9\u65B9\u73A9\u5BB6\u7684 SteamID64\u3002\u4E0E vanityUrl \u4E8C\u9009\u4E00\u3002"),
|
|
39494
39590
|
vanityUrl: z3.string().optional().describe("\u5BF9\u65B9\u73A9\u5BB6\u7684\u81EA\u5B9A\u4E49\u4E3B\u9875\u6807\u8BC6\u3002\u4E0E steamid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -39528,7 +39624,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39528
39624
|
"steam_me_backlog_candidates",
|
|
39529
39625
|
{
|
|
39530
39626
|
title: "\u6211\u7684\u79EF\u538B\u5019\u9009",
|
|
39531
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39627
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E13\u9879\u89C6\u56FE\uFF0C\u4ECE\u6211\u7684\u5E93\u91CC\u6311\u51FA\u503C\u5F97\u5F00\u5751\u7684\u79EF\u538B\u6E38\u620F\u3002",
|
|
39532
39628
|
inputSchema: {
|
|
39533
39629
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39534
39630
|
limit: z3.number().int().min(1).max(30).optional().describe("\u6700\u591A\u8FD4\u56DE\u591A\u5C11\u4E2A\u5019\u9009\uFF0C\u9ED8\u8BA4 12\u3002"),
|
|
@@ -39571,7 +39667,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39571
39667
|
"steam_me_achievement_hunt",
|
|
39572
39668
|
{
|
|
39573
39669
|
title: "\u6211\u7684\u6210\u5C31\u8865\u5B8C\u5019\u9009",
|
|
39574
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39670
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E13\u9879\u89C6\u56FE\uFF0C\u627E\u51FA\u79BB\u5168\u6210\u5C31\u4E0D\u8FDC\u7684\u6E38\u620F\u3002",
|
|
39575
39671
|
inputSchema: {
|
|
39576
39672
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39577
39673
|
language: z3.string().optional().describe("\u8BED\u8A00\u4EE3\u7801\uFF0C\u4F8B\u5982 schinese \u6216 english\u3002"),
|
|
@@ -39620,7 +39716,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39620
39716
|
"steam_me_game_snapshot",
|
|
39621
39717
|
{
|
|
39622
39718
|
title: "\u6211\u7684\u6E38\u620F\u5FEB\u7167",
|
|
39623
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39719
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u5355\u6E38\u620F\u4E3B\u5165\u53E3\uFF0C\u67E5\u770B\u6211\u4E0E\u67D0\u4E2A\u6E38\u620F\u7684\u5173\u7CFB\u3001\u65B0\u95FB\u548C\u6210\u5C31\u3002",
|
|
39624
39720
|
inputSchema: {
|
|
39625
39721
|
appid: z3.union([z3.string(), z3.number()]).optional().describe("Steam AppID\u3002\u4E0E query \u4E8C\u9009\u4E00\u3002"),
|
|
39626
39722
|
query: z3.union([z3.string(), z3.number()]).optional().describe("\u6E38\u620F\u540D\u6216 AppID\uFF0C\u652F\u6301\u76F4\u63A5\u8F93\u5165\u4E2D\u6587\u540D\u3002\u4E0E appid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -39673,7 +39769,7 @@ function registerMyAccountTools(server, runtime2) {
|
|
|
39673
39769
|
"steam_me_game_feed",
|
|
39674
39770
|
{
|
|
39675
39771
|
title: "\u6211\u7684\u6E38\u620F\u52A8\u6001\u6D41",
|
|
39676
|
-
description: "\u9ED8\u8BA4\u8D26\u53F7\
|
|
39772
|
+
description: "\u9ED8\u8BA4\u8D26\u53F7\u4E13\u9879\u89C6\u56FE\uFF0C\u6309\u6700\u8FD1\u6E38\u73A9\u3001\u5E38\u73A9\u6216\u663E\u5F0F App \u751F\u6210\u4E2A\u4EBA\u6E38\u620F\u52A8\u6001\u6D41\u3002",
|
|
39677
39773
|
inputSchema: {
|
|
39678
39774
|
key: z3.string().optional().describe("\u53EF\u9009\u7684 Steam Web API key \u8986\u76D6\u503C\u3002"),
|
|
39679
39775
|
source: z3.enum(["recent", "topOwned", "mixed", "explicit"]).optional().describe("\u52A8\u6001\u6D41\u7684\u6E38\u620F\u6765\u6E90\uFF0C\u9ED8\u8BA4 recent\u3002"),
|
|
@@ -39725,7 +39821,7 @@ function registerOverviewTools(server, runtime2) {
|
|
|
39725
39821
|
"steam_get_player_profile_overview",
|
|
39726
39822
|
{
|
|
39727
39823
|
title: "\u73A9\u5BB6\u8D44\u6599\u603B\u89C8",
|
|
39728
|
-
description: "\u805A\u5408\u73A9\u5BB6\u8D44\u6599\u3001\u5C01\u7981\u3001\u7B49\u7EA7\u3001\u5FBD\u7AE0\u548C\u6700\u8FD1\u6E38\u73A9\u4FE1\u606F\u3002",
|
|
39824
|
+
description: "\u901A\u7528\u73A9\u5BB6\u4E3B\u5165\u53E3\uFF0C\u805A\u5408\u73A9\u5BB6\u8D44\u6599\u3001\u5C01\u7981\u3001\u7B49\u7EA7\u3001\u5FBD\u7AE0\u548C\u6700\u8FD1\u6E38\u73A9\u4FE1\u606F\u3002",
|
|
39729
39825
|
inputSchema: {
|
|
39730
39826
|
steamid: z4.union([z4.string(), z4.number()]).optional().describe("\u73A9\u5BB6\u7684 SteamID64\u3002\u4E0E vanityUrl \u4E8C\u9009\u4E00\u3002"),
|
|
39731
39827
|
vanityUrl: z4.string().optional().describe("\u73A9\u5BB6\u7684\u81EA\u5B9A\u4E49\u4E3B\u9875\u6807\u8BC6\uFF0C\u4F8B\u5982 gaben\u3002\u4E0E steamid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -39759,7 +39855,7 @@ function registerOverviewTools(server, runtime2) {
|
|
|
39759
39855
|
"steam_get_library_overview",
|
|
39760
39856
|
{
|
|
39761
39857
|
title: "\u6E38\u620F\u5E93\u603B\u89C8",
|
|
39762
|
-
description: "\u805A\u5408\u73A9\u5BB6\u62E5\u6709\u7684\u6E38\u620F\u3001\u6700\u8FD1\u6E38\u73A9\u548C\u5E38\u73A9\u6E38\u620F\u3002",
|
|
39858
|
+
description: "\u901A\u7528\u73A9\u5BB6\u6E38\u620F\u5E93\u4E3B\u5165\u53E3\uFF0C\u805A\u5408\u73A9\u5BB6\u62E5\u6709\u7684\u6E38\u620F\u3001\u6700\u8FD1\u6E38\u73A9\u548C\u5E38\u73A9\u6E38\u620F\u3002",
|
|
39763
39859
|
inputSchema: {
|
|
39764
39860
|
steamid: z4.union([z4.string(), z4.number()]).optional().describe("\u73A9\u5BB6\u7684 SteamID64\u3002\u4E0E vanityUrl \u4E8C\u9009\u4E00\u3002"),
|
|
39765
39861
|
vanityUrl: z4.string().optional().describe("\u73A9\u5BB6\u7684\u81EA\u5B9A\u4E49\u4E3B\u9875\u6807\u8BC6\uFF0C\u4F8B\u5982 gaben\u3002\u4E0E steamid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -39802,7 +39898,7 @@ function registerOverviewTools(server, runtime2) {
|
|
|
39802
39898
|
"steam_get_player_game_achievements",
|
|
39803
39899
|
{
|
|
39804
39900
|
title: "\u73A9\u5BB6\u6E38\u620F\u6210\u5C31",
|
|
39805
|
-
description: "\u67E5\u770B\u67D0\u4E2A\u73A9\u5BB6\u5728\u67D0\u4E2A\u6E38\u620F\u91CC\u7684\u6210\u5C31\u3001\u5B8C\u6210\u7387\u548C\u53EF\u9009\u7EDF\u8BA1\u3002",
|
|
39901
|
+
description: "\u901A\u7528\u73A9\u5BB6\u5355\u6E38\u620F\u4E13\u9879\u89C6\u56FE\uFF0C\u67E5\u770B\u67D0\u4E2A\u73A9\u5BB6\u5728\u67D0\u4E2A\u6E38\u620F\u91CC\u7684\u6210\u5C31\u3001\u5B8C\u6210\u7387\u548C\u53EF\u9009\u7EDF\u8BA1\u3002",
|
|
39806
39902
|
inputSchema: {
|
|
39807
39903
|
steamid: z4.union([z4.string(), z4.number()]).optional().describe("\u73A9\u5BB6\u7684 SteamID64\u3002\u4E0E vanityUrl \u4E8C\u9009\u4E00\u3002"),
|
|
39808
39904
|
vanityUrl: z4.string().optional().describe("\u73A9\u5BB6\u7684\u81EA\u5B9A\u4E49\u4E3B\u9875\u6807\u8BC6\uFF0C\u4F8B\u5982 gaben\u3002\u4E0E steamid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -39845,7 +39941,7 @@ function registerOverviewTools(server, runtime2) {
|
|
|
39845
39941
|
"steam_get_app_news",
|
|
39846
39942
|
{
|
|
39847
39943
|
title: "\u6E38\u620F\u65B0\u95FB",
|
|
39848
|
-
description: "\u67E5\u770B\u67D0\u4E2A\u6E38\u620F\u7684 Steam \u65B0\u95FB\uFF0C\u5E76\u53EF\u9009\u9644\u5E26\u5F53\u524D\u5728\u7EBF\u4EBA\u6570\u3002",
|
|
39944
|
+
description: "\u516C\u5171\u5355\u6E38\u620F\u4E13\u9879\u89C6\u56FE\uFF0C\u67E5\u770B\u67D0\u4E2A\u6E38\u620F\u7684 Steam \u65B0\u95FB\uFF0C\u5E76\u53EF\u9009\u9644\u5E26\u5F53\u524D\u5728\u7EBF\u4EBA\u6570\u3002",
|
|
39849
39945
|
inputSchema: {
|
|
39850
39946
|
appid: z4.union([z4.string(), z4.number()]).optional().describe("Steam AppID\u3002\u4E0E query \u4E8C\u9009\u4E00\u3002"),
|
|
39851
39947
|
query: z4.union([z4.string(), z4.number()]).optional().describe("\u6E38\u620F\u540D\u6216 AppID\uFF0C\u652F\u6301\u76F4\u63A5\u8F93\u5165\u4E2D\u6587\u540D\u3002\u4E0E appid \u4E8C\u9009\u4E00\u3002"),
|
|
@@ -39894,8 +39990,8 @@ var runtime = createSteamBaseRuntime(spec, {
|
|
|
39894
39990
|
});
|
|
39895
39991
|
function createServer() {
|
|
39896
39992
|
const server = new McpServer({
|
|
39897
|
-
name:
|
|
39898
|
-
version:
|
|
39993
|
+
name: PACKAGE_NAME,
|
|
39994
|
+
version: PACKAGE_VERSION,
|
|
39899
39995
|
websiteUrl: "https://partner.steamgames.com/doc/webapi"
|
|
39900
39996
|
});
|
|
39901
39997
|
registerOverviewTools(server, runtime);
|