mcp-scraper 0.77.0 → 0.78.0
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/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/dist/{analytics-repository-AUTJK4HK.js → analytics-repository-D5LEGQG3.js} +3 -3
- package/dist/bin/api-server.js +4 -4
- package/dist/bin/mcp-scraper-cli.js +3 -3
- package/dist/bin/mcp-scraper-core.js +7 -7
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.js +7 -7
- package/dist/bin/paa-harvest.js +4 -4
- package/dist/{chunk-DTJ56S5B.js → chunk-2P2ZVRPK.js} +189 -57
- package/dist/{chunk-E6Y3VCOJ.js → chunk-3PUMNEOC.js} +3 -3
- package/dist/{chunk-KIPIBPUB.js → chunk-47ZCUBM5.js} +1 -1
- package/dist/{chunk-IBQNOZ7E.js → chunk-74CCAY6T.js} +1 -1
- package/dist/{chunk-7RQULQF3.js → chunk-B6L73AO4.js} +1 -1
- package/dist/{chunk-WFQ2E4WE.js → chunk-BTQ23KCT.js} +1 -1
- package/dist/{chunk-IP7UDXMU.js → chunk-FODYEDZK.js} +3 -3
- package/dist/{chunk-PJEEKOUM.js → chunk-FUMG43EN.js} +1 -1
- package/dist/{chunk-GT6MP4SU.js → chunk-IYYRSVRQ.js} +1 -1
- package/dist/{chunk-A66DGFOU.js → chunk-KAGHJQFO.js} +1 -1
- package/dist/{chunk-CXY5WV45.js → chunk-NGLZ6UJR.js} +1 -1
- package/dist/{chunk-WEFPBAAG.js → chunk-OU4FV2RP.js} +140 -4
- package/dist/{chunk-F5TK4KMT.js → chunk-OUBH6XMY.js} +1 -1
- package/dist/{chunk-77LQV73B.js → chunk-OWF2JJKN.js} +13 -1
- package/dist/{chunk-F6MUGMRN.js → chunk-UFJJGXVO.js} +702 -165
- package/dist/{chunk-KBTUPRTF.js → chunk-VEQPA65D.js} +1 -1
- package/dist/{chunk-D2O7V2CT.js → chunk-VMWSXKUQ.js} +1 -1
- package/dist/{chunk-7HF3T7P2.js → chunk-ZUCU2A6V.js} +1 -1
- package/dist/{db-566MOHHD.js → db-TA567JLA.js} +17 -1
- package/dist/{extract-bundle-OO74L67T.js → extract-bundle-P2DTUVY3.js} +3 -3
- package/dist/{gmail-service-TIU4V5JA.js → gmail-service-HN57R2GS.js} +4 -4
- package/dist/index.cjs +714 -165
- package/dist/index.d.cts +83 -1
- package/dist/index.d.ts +83 -1
- package/dist/index.js +4 -4
- package/dist/{lead-list-enrichment-repository-WWEMJ7EN.js → lead-list-enrichment-repository-5LEWW4X7.js} +2 -2
- package/dist/{location-data-repository-H4B2BWGY.js → location-data-repository-AHKDXTEQ.js} +2 -2
- package/dist/{server-EKRNKKLU.js → server-6B2OG3NN.js} +312 -89
- package/dist/{site-extract-repository-B47JB62U.js → site-extract-repository-XKSVXSSY.js} +2 -2
- package/dist/{worker-DR6R7J46.js → worker-2BYACLNF.js} +6 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ All notable changes to MCP Scraper are documented here. The format is based on [
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.78.0] - 2026-08-28
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Made `maxQuestions` an explicit target count rather than a traversal-depth control, with separate discovery and material-completeness diagnostics.
|
|
12
|
+
- Preserved complete People Also Ask, AI Overview, and organic-result link provenance in JSON, structured MCP output, and CSV while classifying plain links and Google redirect links explicitly.
|
|
13
|
+
- Resolved opaque Google `/goto` targets through bounded concurrent manual-redirect requests with active-browser interception as a fallback, without following publisher destinations and without dropping unresolved material.
|
|
14
|
+
- Aligned the bounded PAA production-provider canary with the public `maxQuestions` contract and made Bright Data the default test provider.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Distinguished a healthy three-pass PAA frontier exhaustion from failed, disappeared, or timed-out browser interactions; interrupted jobs now renew fenced leases, resume automatically on the same job ID, and stop after a bounded recovery budget.
|
|
19
|
+
- Checkpointed the initial SERP material before PAA expansion so a worker interruption retains already captured AI Overview citations, organic rankings, entities, forums, videos, and local results.
|
|
20
|
+
- Required an exact visible AI Overview label before accepting an overview container, preventing ordinary sponsored blocks from being misclassified as AI answers.
|
|
21
|
+
- Kept synchronous and durable PAA results consistent for question identifiers, all answer sources, SERP modules, link-resolution status, and completeness diagnostics.
|
|
22
|
+
|
|
7
23
|
## [0.77.0] - 2026-08-28
|
|
8
24
|
|
|
9
25
|
### Fixed
|
package/README.md
CHANGED
|
@@ -174,7 +174,7 @@ Build the branded one-click bundle:
|
|
|
174
174
|
npm run build:mcpb
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.
|
|
177
|
+
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.78.0`, SHA-256 `24ff5a133390938baa00e38a6489dd46e4f143fb26d9d2759e0983e134a946a7`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, API-key configuration field, and manually curated current-release message from the bundle manifest.
|
|
178
178
|
|
|
179
179
|
The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
|
|
180
180
|
|
|
@@ -85,9 +85,9 @@ import {
|
|
|
85
85
|
updateAnalyticsPixel,
|
|
86
86
|
upsertAnalyticsAdSpend,
|
|
87
87
|
upsertAnalyticsHostGroup
|
|
88
|
-
} from "./chunk-
|
|
89
|
-
import "./chunk-
|
|
90
|
-
import "./chunk-
|
|
88
|
+
} from "./chunk-74CCAY6T.js";
|
|
89
|
+
import "./chunk-FUMG43EN.js";
|
|
90
|
+
import "./chunk-OU4FV2RP.js";
|
|
91
91
|
export {
|
|
92
92
|
ANALYTICS_CONTENT_SORTS,
|
|
93
93
|
AnalyticsRepositoryError,
|
package/dist/bin/api-server.js
CHANGED
|
@@ -17,15 +17,15 @@ loadDotEnv();
|
|
|
17
17
|
async function main() {
|
|
18
18
|
const [{ serve }, { app }, { startWorker }, { migrate }] = await Promise.all([
|
|
19
19
|
import("@hono/node-server"),
|
|
20
|
-
import("../server-
|
|
21
|
-
import("../worker-
|
|
22
|
-
import("../db-
|
|
20
|
+
import("../server-6B2OG3NN.js"),
|
|
21
|
+
import("../worker-2BYACLNF.js"),
|
|
22
|
+
import("../db-TA567JLA.js")
|
|
23
23
|
]);
|
|
24
24
|
const PORT = parseInt(process.env.PORT ?? "3001");
|
|
25
25
|
try {
|
|
26
26
|
await migrate();
|
|
27
27
|
if (process.env.ANALYTICS_DATABASE_URL) {
|
|
28
|
-
const { migrateAnalytics } = await import("../analytics-repository-
|
|
28
|
+
const { migrateAnalytics } = await import("../analytics-repository-D5LEGQG3.js");
|
|
29
29
|
await migrateAnalytics();
|
|
30
30
|
}
|
|
31
31
|
startWorker();
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
openWorkflowReport,
|
|
7
7
|
runWorkflow,
|
|
8
8
|
workflowOutputBaseDir
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-VEQPA65D.js";
|
|
10
10
|
import "../chunk-RJ7JVYKU.js";
|
|
11
|
-
import "../chunk-
|
|
11
|
+
import "../chunk-OWF2JJKN.js";
|
|
12
12
|
import "../chunk-VXLU74YZ.js";
|
|
13
13
|
import "../chunk-GGZEC22A.js";
|
|
14
14
|
import {
|
|
15
15
|
PACKAGE_VERSION
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-ZUCU2A6V.js";
|
|
17
17
|
|
|
18
18
|
// src/cli/human-cli.ts
|
|
19
19
|
import { Command } from "commander";
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runMcpScraperStdio
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-FODYEDZK.js";
|
|
5
|
+
import "../chunk-2P2ZVRPK.js";
|
|
6
6
|
import "../chunk-PGJQDMC2.js";
|
|
7
7
|
import "../chunk-DNM65UCK.js";
|
|
8
8
|
import "../chunk-T3MZISOF.js";
|
|
9
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-B6L73AO4.js";
|
|
10
10
|
import "../chunk-6W4ADSWE.js";
|
|
11
11
|
import "../chunk-OM7HVEJ3.js";
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-NGLZ6UJR.js";
|
|
13
|
+
import "../chunk-IYYRSVRQ.js";
|
|
14
14
|
import "../chunk-VXLU74YZ.js";
|
|
15
15
|
import "../chunk-GGZEC22A.js";
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
16
|
+
import "../chunk-ZUCU2A6V.js";
|
|
17
|
+
import "../chunk-OU4FV2RP.js";
|
|
18
18
|
|
|
19
19
|
// src/mcp/thorbit-restricted-tool-surface.ts
|
|
20
20
|
var THORBIT_RESTRICTED_TOOL_NAMES = [
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
renderInstallTerminal
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-IYYRSVRQ.js";
|
|
5
5
|
import {
|
|
6
6
|
PACKAGE_VERSION
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-ZUCU2A6V.js";
|
|
8
8
|
|
|
9
9
|
// bin/mcp-scraper-install.ts
|
|
10
10
|
var noColor = process.argv.includes("--no-color") || process.env.NO_COLOR !== void 0 || process.env.FORCE_COLOR === "0" || !process.stdout.isTTY;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runMcpScraperStdio
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-FODYEDZK.js";
|
|
5
|
+
import "../chunk-2P2ZVRPK.js";
|
|
6
6
|
import "../chunk-PGJQDMC2.js";
|
|
7
7
|
import "../chunk-DNM65UCK.js";
|
|
8
8
|
import "../chunk-T3MZISOF.js";
|
|
9
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-B6L73AO4.js";
|
|
10
10
|
import "../chunk-6W4ADSWE.js";
|
|
11
11
|
import "../chunk-OM7HVEJ3.js";
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-NGLZ6UJR.js";
|
|
13
|
+
import "../chunk-IYYRSVRQ.js";
|
|
14
14
|
import "../chunk-VXLU74YZ.js";
|
|
15
15
|
import "../chunk-GGZEC22A.js";
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
16
|
+
import "../chunk-ZUCU2A6V.js";
|
|
17
|
+
import "../chunk-OU4FV2RP.js";
|
|
18
18
|
|
|
19
19
|
// bin/mcp-stdio-server.ts
|
|
20
20
|
runMcpScraperStdio();
|
package/dist/bin/paa-harvest.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
harvest
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-UFJJGXVO.js";
|
|
5
5
|
import {
|
|
6
6
|
browserServiceApiKey
|
|
7
7
|
} from "../chunk-OM7HVEJ3.js";
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-NGLZ6UJR.js";
|
|
9
|
+
import "../chunk-OWF2JJKN.js";
|
|
10
|
+
import "../chunk-OU4FV2RP.js";
|
|
11
11
|
|
|
12
12
|
// src/cli.ts
|
|
13
13
|
import { Command } from "commander";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./chunk-T3MZISOF.js";
|
|
20
20
|
import {
|
|
21
21
|
sanitizeOutboundDiagnostics
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-B6L73AO4.js";
|
|
23
23
|
import {
|
|
24
24
|
MC_PER_CREDIT,
|
|
25
25
|
PAA_BASE_CREDITS,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
import {
|
|
35
35
|
recordVendorUsage,
|
|
36
36
|
vendorCostUsd
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-NGLZ6UJR.js";
|
|
38
38
|
import {
|
|
39
39
|
buildSerpEmailQuery,
|
|
40
40
|
classifyEmailScope,
|
|
@@ -45,14 +45,14 @@ import {
|
|
|
45
45
|
} from "./chunk-VXLU74YZ.js";
|
|
46
46
|
import {
|
|
47
47
|
PACKAGE_VERSION
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-ZUCU2A6V.js";
|
|
49
49
|
import {
|
|
50
50
|
PUBLIC_ERROR_CODES,
|
|
51
51
|
buildPublicErrorEnvelope,
|
|
52
52
|
normalizePublicErrorCode,
|
|
53
53
|
publicErrorMessage,
|
|
54
54
|
sanitizeVendorName
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-OU4FV2RP.js";
|
|
56
56
|
|
|
57
57
|
// src/harvest-timeout.ts
|
|
58
58
|
var SCRAPE_FUNCTION_MAX_MS = 8e5;
|
|
@@ -1121,6 +1121,100 @@ function errorAttemptsSection(body) {
|
|
|
1121
1121
|
Attempts:
|
|
1122
1122
|
${lines.join("\n")}`;
|
|
1123
1123
|
}
|
|
1124
|
+
function publicPaaLifecycle(value) {
|
|
1125
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
1126
|
+
const row = value;
|
|
1127
|
+
const discoveryStatus = nullableBoundedString(row.discoveryStatus, 100);
|
|
1128
|
+
if (!discoveryStatus) return null;
|
|
1129
|
+
const requestedQuestions = finiteNonNegative(row.requestedQuestions) ?? 0;
|
|
1130
|
+
const questionsFound = finiteNonNegative(row.questionsFound) ?? 0;
|
|
1131
|
+
return {
|
|
1132
|
+
requestedQuestions,
|
|
1133
|
+
questionsFound,
|
|
1134
|
+
targetStatus: row.targetStatus === "met" ? "met" : "not_met",
|
|
1135
|
+
discoveryStatus,
|
|
1136
|
+
materialStatus: row.materialStatus === "complete" ? "complete" : "partial",
|
|
1137
|
+
completionReason: nullableBoundedString(row.completionReason, 1e3) ?? "",
|
|
1138
|
+
automaticRetries: finiteNonNegative(row.automaticRetries) ?? 0,
|
|
1139
|
+
knownQuestions: finiteNonNegative(row.knownQuestions) ?? questionsFound,
|
|
1140
|
+
processedQuestions: finiteNonNegative(row.processedQuestions) ?? 0,
|
|
1141
|
+
failedInteractions: finiteNonNegative(row.failedInteractions) ?? 0,
|
|
1142
|
+
noGrowthConfirmations: finiteNonNegative(row.noGrowthConfirmations) ?? 0
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
function publicPaaSource(value) {
|
|
1146
|
+
if (!value || typeof value !== "object") return null;
|
|
1147
|
+
const source = value;
|
|
1148
|
+
const rawUrl = nullableBoundedString(source.rawUrl ?? source.url, 8e3);
|
|
1149
|
+
if (!rawUrl) return null;
|
|
1150
|
+
return {
|
|
1151
|
+
title: nullableBoundedString(source.title, 2e3),
|
|
1152
|
+
site: nullableBoundedString(source.site, 2e3),
|
|
1153
|
+
url: nullableBoundedString(source.url, 8e3) ?? rawUrl,
|
|
1154
|
+
rawUrl,
|
|
1155
|
+
resolvedUrl: nullableBoundedString(source.resolvedUrl, 8e3),
|
|
1156
|
+
linkType: nullableBoundedString(source.linkType, 100) ?? "plain",
|
|
1157
|
+
resolutionStatus: nullableBoundedString(source.resolutionStatus, 100) ?? "not_needed"
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
function publicPaaQuestion(row) {
|
|
1161
|
+
const sources = Array.isArray(row.sources) ? row.sources.flatMap((value) => {
|
|
1162
|
+
const source = publicPaaSource(value);
|
|
1163
|
+
return source ? [source] : [];
|
|
1164
|
+
}) : [];
|
|
1165
|
+
const legacyUrl = nullableBoundedString(row.source_cite ?? row.sourceCite ?? row.source_url ?? row.sourceUrl, 8e3);
|
|
1166
|
+
return {
|
|
1167
|
+
questionId: nullableBoundedString(row.question_id ?? row.questionId, 100) ?? "",
|
|
1168
|
+
googleLinkId: nullableBoundedString(row.google_link_id ?? row.googleLinkId, 2e3),
|
|
1169
|
+
googleEvidenceId: nullableBoundedString(row.google_evidence_id ?? row.googleEvidenceId, 2e3),
|
|
1170
|
+
question: String(row.question ?? ""),
|
|
1171
|
+
answer: nullableBoundedString(row.answer, 5e4),
|
|
1172
|
+
sources,
|
|
1173
|
+
sourceTitle: nullableBoundedString(row.source_title ?? row.sourceTitle, 2e3) ?? sources[0]?.title ?? null,
|
|
1174
|
+
sourceSite: nullableBoundedString(row.source_site ?? row.sourceSite, 2e3) ?? sources[0]?.site ?? null,
|
|
1175
|
+
sourceUrl: legacyUrl ?? sources[0]?.url ?? null
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
function publicOrganicResult(row) {
|
|
1179
|
+
const url = String(row.url ?? "");
|
|
1180
|
+
return {
|
|
1181
|
+
position: Number(row.position) || 0,
|
|
1182
|
+
title: String(row.title ?? ""),
|
|
1183
|
+
url,
|
|
1184
|
+
rawUrl: String(row.rawUrl ?? url),
|
|
1185
|
+
resolvedUrl: nullableBoundedString(row.resolvedUrl, 8e3),
|
|
1186
|
+
linkType: nullableBoundedString(row.linkType, 100) ?? "plain",
|
|
1187
|
+
resolutionStatus: nullableBoundedString(row.resolutionStatus, 100) ?? "not_needed",
|
|
1188
|
+
domain: String(row.domain ?? ""),
|
|
1189
|
+
snippet: nullableBoundedString(row.snippet, 5e4)
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
function publicAiOverview(value) {
|
|
1193
|
+
if (!value || typeof value !== "object") return null;
|
|
1194
|
+
const ai = value;
|
|
1195
|
+
return {
|
|
1196
|
+
detected: ai.detected === true,
|
|
1197
|
+
text: nullableBoundedString(ai.text, 1e5),
|
|
1198
|
+
citations: Array.isArray(ai.citations) ? ai.citations.flatMap((value2) => {
|
|
1199
|
+
if (!value2 || typeof value2 !== "object") return [];
|
|
1200
|
+
const citation = value2;
|
|
1201
|
+
const rawUrl = nullableBoundedString(citation.rawUrl ?? citation.rawHref ?? citation.href, 8e3);
|
|
1202
|
+
if (!rawUrl) return [];
|
|
1203
|
+
return [{
|
|
1204
|
+
text: String(citation.text ?? ""),
|
|
1205
|
+
href: nullableBoundedString(citation.href ?? citation.url, 8e3) ?? rawUrl,
|
|
1206
|
+
rawUrl,
|
|
1207
|
+
resolvedUrl: nullableBoundedString(citation.resolvedUrl, 8e3),
|
|
1208
|
+
linkType: nullableBoundedString(citation.linkType, 100) ?? "plain",
|
|
1209
|
+
resolutionStatus: nullableBoundedString(citation.resolutionStatus, 100) ?? "not_needed"
|
|
1210
|
+
}];
|
|
1211
|
+
}) : [],
|
|
1212
|
+
expanded: ai.expanded === true,
|
|
1213
|
+
fullyExpanded: ai.fullyExpanded === true,
|
|
1214
|
+
sections: Array.isArray(ai.sections) ? ai.sections.map(String) : [],
|
|
1215
|
+
shareUrl: nullableBoundedString(ai.shareUrl, 8e3)
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1124
1218
|
function formatHarvestPaa(raw, input) {
|
|
1125
1219
|
const parsed = parseData(raw);
|
|
1126
1220
|
if ("error" in parsed) return formattedErrorResult(parsed.error);
|
|
@@ -1139,7 +1233,7 @@ function formatHarvestPaa(raw, input) {
|
|
|
1139
1233
|
|---|----------|--------|--------|
|
|
1140
1234
|
${paaRows}` : "## People Also Ask\n*Google did not return a People Also Ask block for this query/location. SERP data was extracted successfully when available.*";
|
|
1141
1235
|
const serpRows = organic.map(
|
|
1142
|
-
(r) => `| ${r.position} | ${cell(r.title)} | [${cell(r.domain)}](${r.url}) | ${cell(truncate(r.snippet, 100))} |`
|
|
1236
|
+
(r) => `| ${r.position} | ${cell(r.title)} | [${cell(r.resolutionStatus === "unresolved" ? "Google redirect (unresolved)" : r.domain)}](${r.url}) | ${cell(truncate(r.snippet, 100))} |`
|
|
1143
1237
|
).join("\n");
|
|
1144
1238
|
const serpTable = organic.length ? `
|
|
1145
1239
|
## Organic Results (${organic.length})
|
|
@@ -1175,20 +1269,10 @@ ${paaTable}${serpTable}${entityIdsSection(entityIds)}${aiSection}${statsLine}${d
|
|
|
1175
1269
|
degradedResult: diagnostics?.degradedResult ?? null,
|
|
1176
1270
|
degradationReasons: diagnostics?.degradationReasons ?? [],
|
|
1177
1271
|
retryRecommended: diagnostics?.retryRecommended ?? null,
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
sourceSite: r.source_site ?? null
|
|
1183
|
-
})),
|
|
1184
|
-
organicResults: organic.map((r) => ({
|
|
1185
|
-
position: Number(r.position) || 0,
|
|
1186
|
-
title: String(r.title ?? ""),
|
|
1187
|
-
url: String(r.url ?? ""),
|
|
1188
|
-
domain: String(r.domain ?? ""),
|
|
1189
|
-
snippet: r.snippet ?? null
|
|
1190
|
-
})),
|
|
1191
|
-
aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null, shareUrl: aiOvw.shareUrl ?? null } : null,
|
|
1272
|
+
paaLifecycle: publicPaaLifecycle(diagnostics?.paaLifecycle),
|
|
1273
|
+
questions: flat.map((r) => publicPaaQuestion(r)),
|
|
1274
|
+
organicResults: organic.map((r) => publicOrganicResult(r)),
|
|
1275
|
+
aiOverview: publicAiOverview(aiOvw),
|
|
1192
1276
|
entityIds: entityIds ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] } : null,
|
|
1193
1277
|
durationMs: durationMs ?? null
|
|
1194
1278
|
}
|
|
@@ -1230,16 +1314,24 @@ function durablePaaProgress(result, options) {
|
|
|
1230
1314
|
const completeness = structuredRecord(diagnostics.completeness ?? result.completeness);
|
|
1231
1315
|
const captured = finiteNonNegative(completeness.questionCount ?? completeness.capturedQuestions) ?? rows.length;
|
|
1232
1316
|
const answered = finiteNonNegative(completeness.answeredQuestions) ?? rows.filter((row) => nullableBoundedString(row.answer) !== null).length;
|
|
1233
|
-
const sourced = finiteNonNegative(completeness.sourcedQuestions) ?? rows.filter((row) => nullableBoundedString(
|
|
1317
|
+
const sourced = finiteNonNegative(completeness.sourcedQuestions) ?? rows.filter((row) => Array.isArray(row.sources) && row.sources.length > 0 || nullableBoundedString(
|
|
1234
1318
|
row.source_cite ?? row.sourceCite ?? row.source_site ?? row.sourceSite ?? row.source_url ?? row.sourceUrl
|
|
1235
1319
|
) !== null).length;
|
|
1320
|
+
const lifecycle = publicPaaLifecycle(diagnostics.paaLifecycle ?? structuredRecord(result.progress).lifecycle);
|
|
1321
|
+
if (lifecycle) {
|
|
1322
|
+
lifecycle.automaticRetries = Math.max(
|
|
1323
|
+
finiteNonNegative(lifecycle.automaticRetries) ?? 0,
|
|
1324
|
+
finiteNonNegative(options.paaRecoveryCount) ?? 0
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1236
1327
|
return {
|
|
1237
1328
|
requestedQuestions: finiteNonNegative(completeness.requestedQuestions ?? options.maxQuestions),
|
|
1238
1329
|
capturedQuestions: captured,
|
|
1239
1330
|
answeredQuestions: answered,
|
|
1240
1331
|
sourcedQuestions: sourced,
|
|
1241
1332
|
missingAnswers: finiteNonNegative(completeness.paaWithoutAnswer ?? completeness.missingAnswers) ?? Math.max(0, captured - answered),
|
|
1242
|
-
missingSources: finiteNonNegative(completeness.paaWithoutSource ?? completeness.missingSources) ?? Math.max(0, captured - sourced)
|
|
1333
|
+
missingSources: finiteNonNegative(completeness.paaWithoutSource ?? completeness.missingSources) ?? Math.max(0, captured - sourced),
|
|
1334
|
+
lifecycle
|
|
1243
1335
|
};
|
|
1244
1336
|
}
|
|
1245
1337
|
function durablePaaResult(result) {
|
|
@@ -1250,14 +1342,12 @@ function durablePaaResult(result) {
|
|
|
1250
1342
|
completionStatus: nullableBoundedString(diagnostics.completionStatus ?? result.completionStatus),
|
|
1251
1343
|
resultQuality: nullableBoundedString(diagnostics.resultQuality ?? result.resultQuality),
|
|
1252
1344
|
retryRecommended: typeof diagnostics.retryRecommended === "boolean" ? diagnostics.retryRecommended : typeof result.retryRecommended === "boolean" ? result.retryRecommended : null,
|
|
1345
|
+
paaLifecycle: publicPaaLifecycle(diagnostics.paaLifecycle ?? structuredRecord(result.progress).lifecycle),
|
|
1253
1346
|
questionCount: rows.length,
|
|
1254
|
-
questions: rows.map(
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
sourceSite: nullableBoundedString(row.source_site ?? row.sourceSite, 2e3),
|
|
1259
|
-
sourceUrl: nullableBoundedString(row.source_cite ?? row.sourceCite ?? row.source_url ?? row.sourceUrl, 8e3)
|
|
1260
|
-
}))
|
|
1347
|
+
questions: rows.map(publicPaaQuestion),
|
|
1348
|
+
organicResults: Array.isArray(result.organicResults) ? result.organicResults.filter((row) => row && typeof row === "object").map((row) => publicOrganicResult(row)) : [],
|
|
1349
|
+
aiOverview: publicAiOverview(result.aiOverview),
|
|
1350
|
+
entityIds: result.entityIds && typeof result.entityIds === "object" ? result.entityIds : null
|
|
1261
1351
|
};
|
|
1262
1352
|
}
|
|
1263
1353
|
function durablePaaAttempts(value) {
|
|
@@ -1332,6 +1422,7 @@ function formatHarvestPaaStatus(raw) {
|
|
|
1332
1422
|
const result = structuredRecord(parsed.data.result);
|
|
1333
1423
|
const options = structuredRecord(parsed.data.options);
|
|
1334
1424
|
const progress = durablePaaProgress(result, options);
|
|
1425
|
+
const recovering = state === "pending" && (finiteNonNegative(options.paaRecoveryCount) ?? 0) > 0;
|
|
1335
1426
|
const holdMc = finiteNonNegative(options.billingHoldMc);
|
|
1336
1427
|
const billedMc = finiteNonNegative(options.billedMc);
|
|
1337
1428
|
const billingSettled = nullableBoundedString(options.billingSettledAt) !== null;
|
|
@@ -1351,7 +1442,10 @@ function formatHarvestPaaStatus(raw) {
|
|
|
1351
1442
|
}
|
|
1352
1443
|
};
|
|
1353
1444
|
return {
|
|
1354
|
-
content: [{
|
|
1445
|
+
content: [{
|
|
1446
|
+
type: "text",
|
|
1447
|
+
text: recovering ? `PAA job ${jobId}: recovering automatically after an interrupted worker. ${progress.capturedQuestions ?? 0} questions are preserved; keep polling this same job.` : `PAA job ${jobId}: ${state}. ${progress.capturedQuestions ?? 0} questions are preserved.`
|
|
1448
|
+
}],
|
|
1355
1449
|
structuredContent
|
|
1356
1450
|
};
|
|
1357
1451
|
}
|
|
@@ -1365,7 +1459,7 @@ function formatSearchSerp(raw, input) {
|
|
|
1365
1459
|
const aiOvw = d.aiOverview;
|
|
1366
1460
|
const diagnostics = d.diagnostics;
|
|
1367
1461
|
const serpRows = organic.map(
|
|
1368
|
-
(r) => `| ${r.position} | ${cell(r.title)} | [${cell(r.domain)}](${r.url}) | ${cell(truncate(r.snippet, 100))} |`
|
|
1462
|
+
(r) => `| ${r.position} | ${cell(r.title)} | [${cell(r.resolutionStatus === "unresolved" ? "Google redirect (unresolved)" : r.domain)}](${r.url}) | ${cell(truncate(r.snippet, 100))} |`
|
|
1369
1463
|
).join("\n");
|
|
1370
1464
|
const serpTable = organic.length ? `## Organic Results (${organic.length})
|
|
1371
1465
|
| # | Title | URL | Snippet |
|
|
@@ -1406,13 +1500,7 @@ ${qualityLine}${serpTable}${localSection}${entityIdsSection(entityIds)}${aiSecti
|
|
|
1406
1500
|
degradedResult: diagnostics?.degradedResult ?? null,
|
|
1407
1501
|
degradationReasons: diagnostics?.degradationReasons ?? [],
|
|
1408
1502
|
retryRecommended: diagnostics?.retryRecommended ?? null,
|
|
1409
|
-
organicResults: organic.map((r) => (
|
|
1410
|
-
position: Number(r.position) || 0,
|
|
1411
|
-
title: String(r.title ?? ""),
|
|
1412
|
-
url: String(r.url ?? ""),
|
|
1413
|
-
domain: String(r.domain ?? ""),
|
|
1414
|
-
snippet: r.snippet ?? null
|
|
1415
|
-
})),
|
|
1503
|
+
organicResults: organic.map((r) => publicOrganicResult(r)),
|
|
1416
1504
|
localPack: localPack.map((b) => ({
|
|
1417
1505
|
position: Number(b.position) || 0,
|
|
1418
1506
|
name: String(b.name ?? ""),
|
|
@@ -1420,7 +1508,7 @@ ${qualityLine}${serpTable}${localSection}${entityIdsSection(entityIds)}${aiSecti
|
|
|
1420
1508
|
reviewCount: b.reviewCount ?? null,
|
|
1421
1509
|
websiteUrl: b.websiteUrl ?? null
|
|
1422
1510
|
})),
|
|
1423
|
-
aiOverview: aiOvw
|
|
1511
|
+
aiOverview: publicAiOverview(aiOvw),
|
|
1424
1512
|
entityIds: entityIds ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] } : null
|
|
1425
1513
|
}
|
|
1426
1514
|
};
|
|
@@ -5422,7 +5510,7 @@ seam is noted so you can chain them.
|
|
|
5422
5510
|
|
|
5423
5511
|
## Search & research
|
|
5424
5512
|
- Organic Google results, rankings, and entity IDs -> **search_serp**. Set the relevant include flag (or \`includeAllSerpFeatures\`) for local pack, forums, videos, AI surfaces, or What People Are Saying.
|
|
5425
|
-
- Original-query People-Also-Ask questions, answers,
|
|
5513
|
+
- Original-query People-Also-Ask questions, answers, complete source/link provenance, AI Overview evidence, organic results, and entity IDs -> **harvest_paa** for a short compatibility call. maxQuestions is a target count, not depth. For expected long work, call **harvest_paa_start** once and poll its job with **harvest_paa_status** until terminal; interrupted workers recover automatically under the same job. Keep the same idempotency key after a timeout, unknown response, recovery, or in-progress reply; never create a replacement key merely because the caller stopped waiting. Treat frontier_exhausted as observed Google-frontier exhaustion and interrupted as non-terminal infrastructure/browser loss, never as the same state. Optional same-page SERP modules use the same include flags.
|
|
5426
5514
|
- \`search_serp\` returns \`organicResults[].url\` (often including reddit.com threads) \u2014 feed those into
|
|
5427
5515
|
\`extract_url\` or \`reddit_thread\`.
|
|
5428
5516
|
|
|
@@ -8388,16 +8476,52 @@ var RankTrackerBlueprintOutputSchema = {
|
|
|
8388
8476
|
metrics: z6.array(z6.string()),
|
|
8389
8477
|
implementationPrompt: z6.string()
|
|
8390
8478
|
};
|
|
8479
|
+
var SerpLinkTypeOutput = z6.enum(["plain", "google_url_redirect", "google_goto_redirect"]);
|
|
8480
|
+
var SerpLinkResolutionStatusOutput = z6.enum(["not_needed", "resolved", "unresolved", "rejected"]);
|
|
8481
|
+
var SerpLinkOutput = {
|
|
8482
|
+
url: z6.string(),
|
|
8483
|
+
rawUrl: z6.string(),
|
|
8484
|
+
resolvedUrl: NullableString,
|
|
8485
|
+
linkType: SerpLinkTypeOutput,
|
|
8486
|
+
resolutionStatus: SerpLinkResolutionStatusOutput
|
|
8487
|
+
};
|
|
8488
|
+
var PaaSourceOutput = z6.object({
|
|
8489
|
+
...SerpLinkOutput,
|
|
8490
|
+
title: NullableString,
|
|
8491
|
+
site: NullableString
|
|
8492
|
+
});
|
|
8493
|
+
var PaaQuestionOutput = z6.object({
|
|
8494
|
+
questionId: z6.string(),
|
|
8495
|
+
googleLinkId: NullableString,
|
|
8496
|
+
googleEvidenceId: NullableString,
|
|
8497
|
+
question: z6.string(),
|
|
8498
|
+
answer: NullableString,
|
|
8499
|
+
sources: z6.array(PaaSourceOutput),
|
|
8500
|
+
sourceTitle: NullableString,
|
|
8501
|
+
sourceSite: NullableString,
|
|
8502
|
+
sourceUrl: NullableString
|
|
8503
|
+
});
|
|
8391
8504
|
var OrganicResultOutput = z6.object({
|
|
8392
8505
|
position: z6.number().int(),
|
|
8393
8506
|
title: z6.string(),
|
|
8394
|
-
|
|
8507
|
+
...SerpLinkOutput,
|
|
8395
8508
|
domain: z6.string(),
|
|
8396
8509
|
snippet: NullableString
|
|
8397
8510
|
});
|
|
8398
8511
|
var AiOverviewOutput = z6.object({
|
|
8399
8512
|
detected: z6.boolean(),
|
|
8400
8513
|
text: NullableString,
|
|
8514
|
+
citations: z6.array(z6.object({
|
|
8515
|
+
text: z6.string(),
|
|
8516
|
+
href: z6.string(),
|
|
8517
|
+
rawUrl: z6.string(),
|
|
8518
|
+
resolvedUrl: NullableString,
|
|
8519
|
+
linkType: SerpLinkTypeOutput,
|
|
8520
|
+
resolutionStatus: SerpLinkResolutionStatusOutput
|
|
8521
|
+
})),
|
|
8522
|
+
expanded: z6.boolean(),
|
|
8523
|
+
fullyExpanded: z6.boolean(),
|
|
8524
|
+
sections: z6.array(z6.string()),
|
|
8401
8525
|
shareUrl: NullableString.optional()
|
|
8402
8526
|
}).nullable();
|
|
8403
8527
|
var EntityIdsOutput = z6.object({
|
|
@@ -8411,6 +8535,19 @@ var EntityIdsOutput = z6.object({
|
|
|
8411
8535
|
cids: z6.array(z6.string()),
|
|
8412
8536
|
gcids: z6.array(z6.string())
|
|
8413
8537
|
}).nullable();
|
|
8538
|
+
var PaaLifecycleOutput = z6.object({
|
|
8539
|
+
requestedQuestions: z6.number().int().min(0),
|
|
8540
|
+
questionsFound: z6.number().int().min(0),
|
|
8541
|
+
targetStatus: z6.enum(["met", "not_met"]),
|
|
8542
|
+
discoveryStatus: z6.enum(["in_progress", "target_reached", "frontier_exhausted", "no_paa_observed", "interrupted", "recovery_exhausted"]),
|
|
8543
|
+
materialStatus: z6.enum(["complete", "partial"]),
|
|
8544
|
+
completionReason: z6.string(),
|
|
8545
|
+
automaticRetries: z6.number().int().min(0),
|
|
8546
|
+
knownQuestions: z6.number().int().min(0),
|
|
8547
|
+
processedQuestions: z6.number().int().min(0),
|
|
8548
|
+
failedInteractions: z6.number().int().min(0),
|
|
8549
|
+
noGrowthConfirmations: z6.number().int().min(0)
|
|
8550
|
+
}).nullable();
|
|
8414
8551
|
var HarvestPaaOutputSchema = {
|
|
8415
8552
|
query: z6.string(),
|
|
8416
8553
|
location: NullableString,
|
|
@@ -8420,12 +8557,8 @@ var HarvestPaaOutputSchema = {
|
|
|
8420
8557
|
degradedResult: z6.boolean().nullable(),
|
|
8421
8558
|
degradationReasons: z6.array(z6.string()),
|
|
8422
8559
|
retryRecommended: z6.boolean().nullable(),
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
answer: NullableString,
|
|
8426
|
-
sourceTitle: NullableString,
|
|
8427
|
-
sourceSite: NullableString
|
|
8428
|
-
})),
|
|
8560
|
+
paaLifecycle: PaaLifecycleOutput,
|
|
8561
|
+
questions: z6.array(PaaQuestionOutput),
|
|
8429
8562
|
organicResults: z6.array(OrganicResultOutput),
|
|
8430
8563
|
aiOverview: AiOverviewOutput,
|
|
8431
8564
|
entityIds: EntityIdsOutput,
|
|
@@ -8437,7 +8570,8 @@ var HarvestPaaDurableProgressOutput = z6.object({
|
|
|
8437
8570
|
answeredQuestions: z6.number().int().min(0),
|
|
8438
8571
|
sourcedQuestions: z6.number().int().min(0),
|
|
8439
8572
|
missingAnswers: z6.number().int().min(0),
|
|
8440
|
-
missingSources: z6.number().int().min(0)
|
|
8573
|
+
missingSources: z6.number().int().min(0),
|
|
8574
|
+
lifecycle: PaaLifecycleOutput
|
|
8441
8575
|
});
|
|
8442
8576
|
var HarvestPaaDurableAttemptOutput = z6.object({
|
|
8443
8577
|
attemptNumber: z6.number().int().min(1),
|
|
@@ -8467,14 +8601,12 @@ var HarvestPaaDurableResultOutput = z6.object({
|
|
|
8467
8601
|
completionStatus: NullableString,
|
|
8468
8602
|
resultQuality: NullableString,
|
|
8469
8603
|
retryRecommended: z6.boolean().nullable(),
|
|
8604
|
+
paaLifecycle: PaaLifecycleOutput,
|
|
8470
8605
|
questionCount: z6.number().int().min(0),
|
|
8471
|
-
questions: z6.array(
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
sourceSite: NullableString,
|
|
8476
|
-
sourceUrl: NullableString
|
|
8477
|
-
}))
|
|
8606
|
+
questions: z6.array(PaaQuestionOutput),
|
|
8607
|
+
organicResults: z6.array(OrganicResultOutput),
|
|
8608
|
+
aiOverview: AiOverviewOutput,
|
|
8609
|
+
entityIds: EntityIdsOutput
|
|
8478
8610
|
});
|
|
8479
8611
|
var HarvestPaaPendingStateOutput = z6.object({
|
|
8480
8612
|
state: z6.literal("pending"),
|
|
@@ -13755,7 +13887,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
13755
13887
|
if (savesReports) registerSavedReportResources(server);
|
|
13756
13888
|
server.registerTool("harvest_paa", {
|
|
13757
13889
|
title: "Google PAA + SERP Harvest",
|
|
13758
|
-
description: `Expand one Google People Also Ask SERP into questions, answers,
|
|
13890
|
+
description: `Expand one Google People Also Ask SERP into questions, answers, every preserved source, AI Overview evidence, ranking URLs, and entity IDs. maxQuestions is a target count, not traversal depth. Results distinguish target_reached, proven frontier_exhausted, interruption, and recovery_exhausted; a failed click or browser timeout is never reported as exhaustion. This compatibility tool waits; use harvest_paa_start plus harvest_paa_status for long runs. Optional SERP modules require their include flags. Use gl and location for regional context. Costs ${PAA_BASE_CREDITS} Credits per harvest plus ${PAA_QUESTION_CREDITS} Credits per question actually returned; unused hold is refunded. After a timeout or unknown response, reuse the same idempotencyKey. Call credits_info for current pricing and balance.`,
|
|
13759
13891
|
inputSchema: harvestPaaInputSchema,
|
|
13760
13892
|
outputSchema: recordOutputSchema("harvest_paa", HarvestPaaOutputSchema),
|
|
13761
13893
|
annotations: liveWebToolAnnotations("Google PAA + SERP Harvest")
|
|
@@ -13768,7 +13900,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
13768
13900
|
});
|
|
13769
13901
|
server.registerTool("harvest_paa_start", {
|
|
13770
13902
|
title: "Start Durable Google PAA Harvest",
|
|
13771
|
-
description: `Start a durable Google People Also Ask harvest and return its job receipt.
|
|
13903
|
+
description: `Start a durable Google People Also Ask harvest and return its job receipt. maxQuestions is the requested target count. The job automatically resumes an interrupted serverless worker under the same jobId, idempotency key, and billing hold while preserving checkpoints. Keep one idempotencyKey after a timeout, unknown response, or in-progress reply; replaying it recovers the existing job without a duplicate charge. Poll jobId with harvest_paa_status. Costs ${PAA_BASE_CREDITS} Credits plus ${PAA_QUESTION_CREDITS} per retained question; unused hold is refunded.`,
|
|
13772
13904
|
inputSchema: harvestPaaStartInputSchema,
|
|
13773
13905
|
outputSchema: recordOutputSchema("harvest_paa_start", HarvestPaaStartOutputSchema),
|
|
13774
13906
|
annotations: { ...liveWebToolAnnotations("Start Durable Google PAA Harvest"), readOnlyHint: false, idempotentHint: true }
|
|
@@ -13778,7 +13910,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
13778
13910
|
});
|
|
13779
13911
|
server.registerTool("harvest_paa_status", {
|
|
13780
13912
|
title: "Check Durable Google PAA Harvest",
|
|
13781
|
-
description: "Poll an owner-scoped harvest_paa_start job. Returns state, saved progress, completeness, attempts, terminal rows, and billing. Polling never starts or bills another run.",
|
|
13913
|
+
description: "Poll an owner-scoped harvest_paa_start job. Returns state, saved progress, automatic-recovery count, target status, discovery status, material completeness, attempts, terminal rows, and billing. frontier_exhausted means every observed eligible PAA control was processed plus three healthy no-growth confirmations; interruption never means exhaustion. Polling never starts or bills another run.",
|
|
13782
13914
|
inputSchema: HarvestPaaStatusInputSchema,
|
|
13783
13915
|
outputSchema: recordOutputSchema("harvest_paa_status", HarvestPaaStatusOutputSchema),
|
|
13784
13916
|
annotations: { ...liveWebToolAnnotations("Check Durable Google PAA Harvest"), idempotentHint: true, openWorldHint: false }
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
recordServiceConnectionHealth,
|
|
6
6
|
setServiceConnectionProviderIdentity,
|
|
7
7
|
updateServiceConnectionTools
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FUMG43EN.js";
|
|
9
9
|
import {
|
|
10
10
|
createConnectedDataArtifact,
|
|
11
11
|
createConnectedDataBinaryArtifact
|
|
@@ -23,13 +23,13 @@ import {
|
|
|
23
23
|
import {
|
|
24
24
|
recordVendorUsage,
|
|
25
25
|
runWithCostContext
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-NGLZ6UJR.js";
|
|
27
27
|
import {
|
|
28
28
|
debitMcIdempotent,
|
|
29
29
|
getDb,
|
|
30
30
|
getUserByEmail,
|
|
31
31
|
reconcileBalanceMc
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-OU4FV2RP.js";
|
|
33
33
|
|
|
34
34
|
// src/api/gmail-service.ts
|
|
35
35
|
import { createHash as createHash4, createHmac, timingSafeEqual } from "crypto";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getSessionSecret,
|
|
3
3
|
serviceConnectionAdvertisesAction
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FUMG43EN.js";
|
|
5
5
|
|
|
6
6
|
// src/api/analytics-repository.ts
|
|
7
7
|
import { createHash as createHash2, createHmac as createHmac2, randomBytes as randomBytes2, randomUUID as randomUUID2 } from "crypto";
|