mcp-scraper 0.4.1 → 0.4.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/dist/bin/api-server.cjs +917 -221
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- package/dist/bin/mcp-scraper-cli.cjs +2 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +3 -3
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +64 -21
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +3 -3
- package/dist/bin/paa-harvest.cjs +1 -0
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +2 -2
- package/dist/{chunk-6TDUY7CA.js → chunk-4MFYMUIF.js} +25 -3
- package/dist/chunk-4MFYMUIF.js.map +1 -0
- package/dist/chunk-7HICT4GY.js +7 -0
- package/dist/chunk-7HICT4GY.js.map +1 -0
- package/dist/{chunk-NNEIXK5L.js → chunk-FUWZWKGO.js} +2 -2
- package/dist/{chunk-QUOZ3LZG.js → chunk-GFY6XHZS.js} +63 -21
- package/dist/chunk-GFY6XHZS.js.map +1 -0
- package/dist/{chunk-HBC4C75S.js → chunk-NJK5BTUK.js} +2 -2
- package/dist/{chunk-JOEZJL4I.js → chunk-NVUBFCJK.js} +2 -2
- package/dist/{chunk-BP27CZ5Q.js → chunk-XGIPATLV.js} +2 -1
- package/dist/chunk-XGIPATLV.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{server-U7V6DUSY.js → server-6IYQQK6X.js} +793 -210
- package/dist/server-6IYQQK6X.js.map +1 -0
- package/dist/{site-extract-repository-2MQBAOX5.js → site-extract-repository-4NVO5KQA.js} +3 -3
- package/dist/{worker-RVZXIALX.js → worker-7XRZNLKB.js} +4 -4
- package/package.json +2 -1
- package/dist/chunk-2ULBZRQQ.js +0 -7
- package/dist/chunk-2ULBZRQQ.js.map +0 -1
- package/dist/chunk-6TDUY7CA.js.map +0 -1
- package/dist/chunk-BP27CZ5Q.js.map +0 -1
- package/dist/chunk-QUOZ3LZG.js.map +0 -1
- package/dist/server-U7V6DUSY.js.map +0 -1
- /package/dist/{chunk-NNEIXK5L.js.map → chunk-FUWZWKGO.js.map} +0 -0
- /package/dist/{chunk-HBC4C75S.js.map → chunk-NJK5BTUK.js.map} +0 -0
- /package/dist/{chunk-JOEZJL4I.js.map → chunk-NVUBFCJK.js.map} +0 -0
- /package/dist/{site-extract-repository-2MQBAOX5.js.map → site-extract-repository-4NVO5KQA.js.map} +0 -0
- /package/dist/{worker-RVZXIALX.js.map → worker-7XRZNLKB.js.map} +0 -0
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
recordVendorUsage,
|
|
17
17
|
resolveKernelProxyId,
|
|
18
18
|
runWithCostContext
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NJK5BTUK.js";
|
|
20
20
|
import {
|
|
21
21
|
HttpMcpToolExecutor,
|
|
22
22
|
MemoryMcpToolExecutor,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
registerSerpIntelligenceCaptureTools,
|
|
32
32
|
sanitizeAttempts,
|
|
33
33
|
sanitizeHarvestResult
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-GFY6XHZS.js";
|
|
35
35
|
import {
|
|
36
36
|
auditImages,
|
|
37
37
|
getBlobStore
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
workflowOutputBaseDir,
|
|
54
54
|
workflowStepCount,
|
|
55
55
|
workflowSupportsSteps
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-FUWZWKGO.js";
|
|
57
57
|
import "./chunk-K443GQY5.js";
|
|
58
58
|
import {
|
|
59
59
|
DEFAULT_MAPS_PROXY_MODE,
|
|
@@ -64,8 +64,8 @@ import {
|
|
|
64
64
|
RawMapsHoursRowSchema,
|
|
65
65
|
RawMapsOverviewSchema,
|
|
66
66
|
RawMapsReviewStatsSchema
|
|
67
|
-
} from "./chunk-
|
|
68
|
-
import "./chunk-
|
|
67
|
+
} from "./chunk-XGIPATLV.js";
|
|
68
|
+
import "./chunk-7HICT4GY.js";
|
|
69
69
|
import {
|
|
70
70
|
completeExtractJob,
|
|
71
71
|
countSuccessfulPages,
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
saveExtractPages,
|
|
77
77
|
setExtractJobTotal,
|
|
78
78
|
settleExtractJob
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-NVUBFCJK.js";
|
|
80
80
|
import {
|
|
81
81
|
BROWSER_OPEN_MIN_BALANCE_MC,
|
|
82
82
|
CONCURRENCY_PRICE_ID,
|
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
browserActiveCostMc,
|
|
96
96
|
concurrencySlotBillingInfo,
|
|
97
97
|
insufficientBalanceResponse
|
|
98
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-4MFYMUIF.js";
|
|
99
99
|
import {
|
|
100
100
|
CaptchaError,
|
|
101
101
|
RECAPTCHA_INSTRUCTIONS,
|
|
@@ -11846,6 +11846,8 @@ function verifySession(token) {
|
|
|
11846
11846
|
}
|
|
11847
11847
|
|
|
11848
11848
|
// src/api/memory.ts
|
|
11849
|
+
import { provisionDefaultsTool } from "mcpscraper-memory-tools/tools/vaults/provision-defaults";
|
|
11850
|
+
import { setScheduleEntitlementTool } from "mcpscraper-memory-tools/tools/schedule/set-schedule-entitlement";
|
|
11849
11851
|
var MEMORY_BASE_URL = () => (process.env.MCP_MEMORY_BASE_URL ?? "https://memory.mcpscraper.dev").replace(/\/$/, "");
|
|
11850
11852
|
var ADMIN_KEY = () => process.env.MCP_MEMORY_ADMIN_KEY?.trim() ?? "";
|
|
11851
11853
|
function parseMemoryRpcBody(text) {
|
|
@@ -11933,6 +11935,24 @@ async function provisionMemoryForUser(user) {
|
|
|
11933
11935
|
} catch {
|
|
11934
11936
|
}
|
|
11935
11937
|
}
|
|
11938
|
+
function memoryPlanForUser(user) {
|
|
11939
|
+
switch (user.subscription_tier) {
|
|
11940
|
+
case "starter":
|
|
11941
|
+
return "pro";
|
|
11942
|
+
case "growth":
|
|
11943
|
+
return "team";
|
|
11944
|
+
case "scale":
|
|
11945
|
+
return "enterprise";
|
|
11946
|
+
default:
|
|
11947
|
+
return "free";
|
|
11948
|
+
}
|
|
11949
|
+
}
|
|
11950
|
+
var MEMORY_PLAN_RANK = { free: 0, pro: 1, team: 2, enterprise: 3 };
|
|
11951
|
+
function resolveEffectiveMemoryPlan(user) {
|
|
11952
|
+
const tierPlan = memoryPlanForUser(user);
|
|
11953
|
+
const memoryProPlan = user.memory_plan === "pro" || user.memory_plan === "team" ? user.memory_plan : "free";
|
|
11954
|
+
return MEMORY_PLAN_RANK[tierPlan] >= MEMORY_PLAN_RANK[memoryProPlan] ? tierPlan : memoryProPlan;
|
|
11955
|
+
}
|
|
11936
11956
|
async function getOrCreateUserMemoryKey(user) {
|
|
11937
11957
|
const creds = await getUserMemoryCreds(user.id);
|
|
11938
11958
|
if (creds.memory_key) {
|
|
@@ -11943,10 +11963,9 @@ async function getOrCreateUserMemoryKey(user) {
|
|
|
11943
11963
|
if (!admin) return { key: null, error: "memory not configured (MCP_MEMORY_ADMIN_KEY missing)" };
|
|
11944
11964
|
const identity = memoryIdentity(user);
|
|
11945
11965
|
const plan = isMemoryOperator(user.email) ? "unlimited" : (await getMemoryPlan(user.id)).plan;
|
|
11946
|
-
const provisioned = await
|
|
11947
|
-
|
|
11948
|
-
{
|
|
11949
|
-
admin
|
|
11966
|
+
const provisioned = await provisionDefaultsTool.execute(
|
|
11967
|
+
{ apiKey: admin, granteeIdentity: identity, issueKey: true, plan },
|
|
11968
|
+
{}
|
|
11950
11969
|
);
|
|
11951
11970
|
if (!provisioned.ok || !provisioned.secret) {
|
|
11952
11971
|
return { key: null, error: provisioned.error ?? "failed to provision default vaults" };
|
|
@@ -11973,12 +11992,13 @@ async function syncScheduleEntitlement(user, enabled, quotaPerPeriod) {
|
|
|
11973
11992
|
const admin = ADMIN_KEY();
|
|
11974
11993
|
if (!admin) return { ok: false, error: "memory not configured (MCP_MEMORY_ADMIN_KEY missing)" };
|
|
11975
11994
|
const identity = resolveMemoryIdentity(user);
|
|
11976
|
-
const res = await
|
|
11995
|
+
const res = await setScheduleEntitlementTool.execute({
|
|
11996
|
+
apiKey: admin,
|
|
11977
11997
|
granteeIdentity: identity,
|
|
11978
11998
|
enabled,
|
|
11979
11999
|
quotaPerPeriod,
|
|
11980
12000
|
mcpScraperApiKey: user.api_key
|
|
11981
|
-
},
|
|
12001
|
+
}, {});
|
|
11982
12002
|
return { ok: res.ok, error: res.error };
|
|
11983
12003
|
}
|
|
11984
12004
|
|
|
@@ -12138,6 +12158,33 @@ var MapsNavigator = class {
|
|
|
12138
12158
|
await this.page.waitForSelector('[role="main"] h2', { timeout: 5e3 }).catch(() => {
|
|
12139
12159
|
});
|
|
12140
12160
|
}
|
|
12161
|
+
async navigateToSerpBusinessPanel(businessName, location2) {
|
|
12162
|
+
const query = `${businessName} ${location2}`;
|
|
12163
|
+
const searchUrl = `https://www.google.com/search?q=${encodeURIComponent(query)}&udm=1`;
|
|
12164
|
+
await this.page.goto(searchUrl, { waitUntil: "domcontentloaded", timeout: 45e3 }).catch(() => {
|
|
12165
|
+
});
|
|
12166
|
+
await this.page.waitForTimeout(2e3);
|
|
12167
|
+
const clicked = await this.page.evaluate((name) => {
|
|
12168
|
+
const trimmedName = name.trim();
|
|
12169
|
+
const words = trimmedName.split(/\s+/);
|
|
12170
|
+
const prefix = words.slice(0, Math.min(2, words.length)).join(" ");
|
|
12171
|
+
const headings = Array.from(document.querySelectorAll('h3, div[role="heading"]'));
|
|
12172
|
+
const heading = headings.find((el2) => el2.innerText?.trim() === trimmedName) ?? headings.find((el2) => el2.innerText?.trim().startsWith(prefix));
|
|
12173
|
+
const clickable = heading?.closest('a, div[role="link"], div[jsaction]');
|
|
12174
|
+
if (clickable) {
|
|
12175
|
+
clickable.click();
|
|
12176
|
+
return true;
|
|
12177
|
+
}
|
|
12178
|
+
if (heading) {
|
|
12179
|
+
heading.click();
|
|
12180
|
+
return true;
|
|
12181
|
+
}
|
|
12182
|
+
return false;
|
|
12183
|
+
}, businessName);
|
|
12184
|
+
if (!clicked) return false;
|
|
12185
|
+
await this.page.waitForTimeout(2e3);
|
|
12186
|
+
return true;
|
|
12187
|
+
}
|
|
12141
12188
|
buildReviewsUrl(placeUrl) {
|
|
12142
12189
|
const fid = placeUrl.match(/!1s(0x[0-9a-f]+:0x[0-9a-f]+)/i);
|
|
12143
12190
|
const pin = placeUrl.match(/!3d(-?\d+\.\d+)!4d(-?\d+\.\d+)/);
|
|
@@ -12307,6 +12354,25 @@ var MapsExtractor = class {
|
|
|
12307
12354
|
}
|
|
12308
12355
|
await navigator.navigateToAboutTab();
|
|
12309
12356
|
const aboutAttributes = await this.extractAbout(page);
|
|
12357
|
+
let services = [];
|
|
12358
|
+
let areasServed = [];
|
|
12359
|
+
let servicesStatus = "not_requested";
|
|
12360
|
+
if (options.includeServices) {
|
|
12361
|
+
try {
|
|
12362
|
+
const opened = await navigator.navigateToSerpBusinessPanel(options.businessName, options.location);
|
|
12363
|
+
if (opened) {
|
|
12364
|
+
const result = await this.extractServicesAndAreasServed(page);
|
|
12365
|
+
services = result.services;
|
|
12366
|
+
areasServed = result.areasServed;
|
|
12367
|
+
servicesStatus = services.length > 0 || areasServed.length > 0 ? "collected" : "none_exist";
|
|
12368
|
+
} else {
|
|
12369
|
+
servicesStatus = "unavailable";
|
|
12370
|
+
}
|
|
12371
|
+
} catch (err) {
|
|
12372
|
+
console.warn("[MapsExtractor] services/areas-served extraction failed:", err instanceof Error ? err.message : String(err));
|
|
12373
|
+
servicesStatus = "unavailable";
|
|
12374
|
+
}
|
|
12375
|
+
}
|
|
12310
12376
|
const reviewCountFinal = overview.reviewCount ?? (reviewStats.reviewHistogram.length > 0 ? reviewStats.reviewHistogram.reduce((s, r) => s + parseInt(r.count, 10), 0).toString() : null);
|
|
12311
12377
|
return {
|
|
12312
12378
|
businessName: options.businessName,
|
|
@@ -12322,6 +12388,9 @@ var MapsExtractor = class {
|
|
|
12322
12388
|
aboutAttributes,
|
|
12323
12389
|
reviews,
|
|
12324
12390
|
reviewsStatus,
|
|
12391
|
+
services,
|
|
12392
|
+
areasServed,
|
|
12393
|
+
servicesStatus,
|
|
12325
12394
|
durationMs: Date.now() - startMs
|
|
12326
12395
|
};
|
|
12327
12396
|
} finally {
|
|
@@ -12510,6 +12579,81 @@ var MapsExtractor = class {
|
|
|
12510
12579
|
}
|
|
12511
12580
|
return result.data;
|
|
12512
12581
|
}
|
|
12582
|
+
async extractServicesAndAreasServed(page) {
|
|
12583
|
+
await page.waitForTimeout(1500);
|
|
12584
|
+
let services = [];
|
|
12585
|
+
if (await this.clickRowStartingWithRetry(page, "Services:")) {
|
|
12586
|
+
await page.waitForSelector('[role="dialog"]', { timeout: 5e3 }).catch(() => {
|
|
12587
|
+
});
|
|
12588
|
+
await page.waitForTimeout(800);
|
|
12589
|
+
services = await this.extractOpenDialogItems(page, "Services");
|
|
12590
|
+
await this.closeOpenDialog(page, "Services");
|
|
12591
|
+
await page.waitForTimeout(500);
|
|
12592
|
+
}
|
|
12593
|
+
let areasServed = [];
|
|
12594
|
+
if (await this.clickRowStartingWithRetry(page, "Serves ")) {
|
|
12595
|
+
await page.waitForSelector('[role="dialog"]', { timeout: 5e3 }).catch(() => {
|
|
12596
|
+
});
|
|
12597
|
+
await page.waitForTimeout(800);
|
|
12598
|
+
areasServed = await this.extractOpenDialogItems(page, "Areas Served");
|
|
12599
|
+
await this.closeOpenDialog(page, "Areas Served");
|
|
12600
|
+
}
|
|
12601
|
+
return { services, areasServed };
|
|
12602
|
+
}
|
|
12603
|
+
async clickRowStartingWithRetry(page, prefix) {
|
|
12604
|
+
if (await this.clickRowStartingWith(page, prefix)) return true;
|
|
12605
|
+
await page.waitForTimeout(2e3);
|
|
12606
|
+
return this.clickRowStartingWith(page, prefix);
|
|
12607
|
+
}
|
|
12608
|
+
async clickRowStartingWith(page, prefix) {
|
|
12609
|
+
return page.evaluate((p) => {
|
|
12610
|
+
const el2 = Array.from(document.querySelectorAll('button, a, div[role="button"]')).find(
|
|
12611
|
+
(e) => (e.innerText ?? "").trim().startsWith(p)
|
|
12612
|
+
);
|
|
12613
|
+
if (!el2) return false;
|
|
12614
|
+
el2.click();
|
|
12615
|
+
return true;
|
|
12616
|
+
}, prefix);
|
|
12617
|
+
}
|
|
12618
|
+
async extractOpenDialogItems(page, expectedHeading) {
|
|
12619
|
+
return page.evaluate((expected) => {
|
|
12620
|
+
const dialogs = Array.from(document.querySelectorAll('[role="dialog"]'));
|
|
12621
|
+
const withHeading = dialogs.find((d) => {
|
|
12622
|
+
const h = d.querySelector('h1, h2, [role="heading"]');
|
|
12623
|
+
const headingText = h?.innerText?.trim() ?? "";
|
|
12624
|
+
return headingText.startsWith(expected);
|
|
12625
|
+
});
|
|
12626
|
+
if (!withHeading) return [];
|
|
12627
|
+
const headingEl = withHeading.querySelector('h1, h2, [role="heading"]');
|
|
12628
|
+
const headingLines = new Set(
|
|
12629
|
+
(headingEl?.innerText ?? "").split("\n").map((s) => s.trim()).filter(Boolean)
|
|
12630
|
+
);
|
|
12631
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12632
|
+
const items = [];
|
|
12633
|
+
withHeading.querySelectorAll("*").forEach((el2) => {
|
|
12634
|
+
if (el2.children.length > 0) return;
|
|
12635
|
+
const text = el2.innerText?.trim() ?? el2.textContent?.trim() ?? "";
|
|
12636
|
+
if (!text || headingLines.has(text)) return;
|
|
12637
|
+
if (/^(back|close|done|thanks)$/i.test(text)) return;
|
|
12638
|
+
if (/^serves\s.*following/i.test(text)) return;
|
|
12639
|
+
if (seen.has(text)) return;
|
|
12640
|
+
seen.add(text);
|
|
12641
|
+
items.push(text);
|
|
12642
|
+
});
|
|
12643
|
+
return items;
|
|
12644
|
+
}, expectedHeading);
|
|
12645
|
+
}
|
|
12646
|
+
async closeOpenDialog(page, expectedHeading) {
|
|
12647
|
+
await page.evaluate((expected) => {
|
|
12648
|
+
const dialog = Array.from(document.querySelectorAll('[role="dialog"]')).find((d) => {
|
|
12649
|
+
const h = d.querySelector('h1, h2, [role="heading"]');
|
|
12650
|
+
const headingText = h?.innerText?.trim() ?? "";
|
|
12651
|
+
return headingText.startsWith(expected);
|
|
12652
|
+
});
|
|
12653
|
+
const closeBtn = dialog?.querySelector('[aria-label*="Close" i], button[aria-label*="close" i]');
|
|
12654
|
+
closeBtn?.click();
|
|
12655
|
+
}, expectedHeading);
|
|
12656
|
+
}
|
|
12513
12657
|
};
|
|
12514
12658
|
|
|
12515
12659
|
// src/extractor/MapsSearchExtractor.ts
|
|
@@ -14908,6 +15052,444 @@ serpIntelligenceApp.post("/page-snapshots", async (c) => {
|
|
|
14908
15052
|
import { Hono as Hono14 } from "hono";
|
|
14909
15053
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
14910
15054
|
|
|
15055
|
+
// src/mcp/memory-inprocess-executor.ts
|
|
15056
|
+
var CUTOVER = /* @__PURE__ */ new Map();
|
|
15057
|
+
function registerCutover(upstreamName, handler) {
|
|
15058
|
+
CUTOVER.set(upstreamName, handler);
|
|
15059
|
+
}
|
|
15060
|
+
var HybridMemoryToolExecutor = class {
|
|
15061
|
+
constructor(httpExecutor, user) {
|
|
15062
|
+
this.httpExecutor = httpExecutor;
|
|
15063
|
+
this.user = user;
|
|
15064
|
+
}
|
|
15065
|
+
httpExecutor;
|
|
15066
|
+
user;
|
|
15067
|
+
mkKeyPromise = null;
|
|
15068
|
+
async resolveMkKey() {
|
|
15069
|
+
if (!this.mkKeyPromise) {
|
|
15070
|
+
this.mkKeyPromise = getOrCreateUserMemoryKey(this.user).then((r) => r.key);
|
|
15071
|
+
}
|
|
15072
|
+
return this.mkKeyPromise;
|
|
15073
|
+
}
|
|
15074
|
+
async callMemoryTool(upstreamName, args) {
|
|
15075
|
+
const handler = CUTOVER.get(upstreamName);
|
|
15076
|
+
if (!handler) return this.httpExecutor.callMemoryTool(upstreamName, args);
|
|
15077
|
+
const mkKey = await this.resolveMkKey();
|
|
15078
|
+
if (!mkKey) return { content: [{ type: "text", text: "memory unavailable" }], isError: true };
|
|
15079
|
+
try {
|
|
15080
|
+
return await handler(args, mkKey);
|
|
15081
|
+
} catch (err) {
|
|
15082
|
+
const message = err instanceof Error ? err.message : `memory ${upstreamName} failed in-process`;
|
|
15083
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
15084
|
+
}
|
|
15085
|
+
}
|
|
15086
|
+
};
|
|
15087
|
+
|
|
15088
|
+
// src/mcp/memory-cutover/reads.ts
|
|
15089
|
+
import { listApprovedSendersTool } from "mcpscraper-memory-tools/tools/access/list-approved-senders";
|
|
15090
|
+
import { noteInboxTool } from "mcpscraper-memory-tools/tools/access/note-inbox";
|
|
15091
|
+
import { getMessageNoteTool } from "mcpscraper-memory-tools/tools/channels/get-message-note";
|
|
15092
|
+
import { listChannelMembersTool } from "mcpscraper-memory-tools/tools/channels/list-channel-members";
|
|
15093
|
+
import { myMentionsTool } from "mcpscraper-memory-tools/tools/channels/my-mentions";
|
|
15094
|
+
import { factHistoryTool } from "mcpscraper-memory-tools/tools/facts/fact-history";
|
|
15095
|
+
import { exportTool } from "mcpscraper-memory-tools/tools/memory/export";
|
|
15096
|
+
import { getTool } from "mcpscraper-memory-tools/tools/memory/get";
|
|
15097
|
+
import { listTool } from "mcpscraper-memory-tools/tools/memory/list";
|
|
15098
|
+
import { searchTool } from "mcpscraper-memory-tools/tools/memory/search";
|
|
15099
|
+
import { suggestTool } from "mcpscraper-memory-tools/tools/memory/suggest";
|
|
15100
|
+
import { temporalRecallTool } from "mcpscraper-memory-tools/tools/recall/temporal-recall";
|
|
15101
|
+
import { listScheduledActionsTool } from "mcpscraper-memory-tools/tools/schedule/list-scheduled-actions";
|
|
15102
|
+
import { costUsageTool } from "mcpscraper-memory-tools/tools/storage/cost-usage";
|
|
15103
|
+
import { storageUsageTool } from "mcpscraper-memory-tools/tools/storage/storage-usage";
|
|
15104
|
+
import { describeTableTool } from "mcpscraper-memory-tools/tools/tables/table-describe";
|
|
15105
|
+
import { listTablesTool } from "mcpscraper-memory-tools/tools/tables/table-list";
|
|
15106
|
+
import { queryTableTool } from "mcpscraper-memory-tools/tools/tables/table-query";
|
|
15107
|
+
import { listSharedWithMeTool } from "mcpscraper-memory-tools/tools/vaults/list-shared-with-me";
|
|
15108
|
+
import { listVaultsTool } from "mcpscraper-memory-tools/tools/vaults/list-vaults";
|
|
15109
|
+
import { videoAnalyzeStatusTool } from "mcpscraper-memory-tools/tools/video/status";
|
|
15110
|
+
import { listWebhooksTool } from "mcpscraper-memory-tools/tools/webhooks/list-webhooks";
|
|
15111
|
+
var registered = false;
|
|
15112
|
+
function registerReadCutovers() {
|
|
15113
|
+
if (registered) return;
|
|
15114
|
+
registered = true;
|
|
15115
|
+
registerCutover("listApprovedSendersTool", async (input, apiKey) => {
|
|
15116
|
+
const result = await listApprovedSendersTool.execute({ ...input, apiKey }, {});
|
|
15117
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15118
|
+
});
|
|
15119
|
+
registerCutover("noteInboxTool", async (input, apiKey) => {
|
|
15120
|
+
const result = await noteInboxTool.execute({ ...input, apiKey }, {});
|
|
15121
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15122
|
+
});
|
|
15123
|
+
registerCutover("getMessageNoteTool", async (input, apiKey) => {
|
|
15124
|
+
const result = await getMessageNoteTool.execute({ ...input, apiKey }, {});
|
|
15125
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15126
|
+
});
|
|
15127
|
+
registerCutover("listChannelMembersTool", async (input, apiKey) => {
|
|
15128
|
+
const result = await listChannelMembersTool.execute({ ...input, apiKey }, {});
|
|
15129
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15130
|
+
});
|
|
15131
|
+
registerCutover("myMentionsTool", async (input, apiKey) => {
|
|
15132
|
+
const result = await myMentionsTool.execute({ ...input, apiKey }, {});
|
|
15133
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15134
|
+
});
|
|
15135
|
+
registerCutover("factHistoryTool", async (input, apiKey) => {
|
|
15136
|
+
const result = await factHistoryTool.execute({ ...input, apiKey }, {});
|
|
15137
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15138
|
+
});
|
|
15139
|
+
registerCutover("exportTool", async (input, apiKey) => {
|
|
15140
|
+
const result = await exportTool.execute({ ...input, apiKey }, {});
|
|
15141
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15142
|
+
});
|
|
15143
|
+
registerCutover("getTool", async (input, apiKey) => {
|
|
15144
|
+
const result = await getTool.execute({ ...input, apiKey }, {});
|
|
15145
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15146
|
+
});
|
|
15147
|
+
registerCutover("listTool", async (input, apiKey) => {
|
|
15148
|
+
const result = await listTool.execute({ ...input, apiKey }, {});
|
|
15149
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15150
|
+
});
|
|
15151
|
+
registerCutover("searchTool", async (input, apiKey) => {
|
|
15152
|
+
const result = await searchTool.execute({ ...input, apiKey }, {});
|
|
15153
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15154
|
+
});
|
|
15155
|
+
registerCutover("suggestTool", async (input, apiKey) => {
|
|
15156
|
+
const result = await suggestTool.execute({ ...input, apiKey }, {});
|
|
15157
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15158
|
+
});
|
|
15159
|
+
registerCutover("temporalRecallTool", async (input, apiKey) => {
|
|
15160
|
+
const result = await temporalRecallTool.execute({ ...input, apiKey }, {});
|
|
15161
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15162
|
+
});
|
|
15163
|
+
registerCutover("listScheduledActionsTool", async (input, apiKey) => {
|
|
15164
|
+
const result = await listScheduledActionsTool.execute({ ...input, apiKey }, {});
|
|
15165
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15166
|
+
});
|
|
15167
|
+
registerCutover("costUsageTool", async (input, apiKey) => {
|
|
15168
|
+
const result = await costUsageTool.execute({ ...input, apiKey }, {});
|
|
15169
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15170
|
+
});
|
|
15171
|
+
registerCutover("storageUsageTool", async (input, apiKey) => {
|
|
15172
|
+
const result = await storageUsageTool.execute({ ...input, apiKey }, {});
|
|
15173
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15174
|
+
});
|
|
15175
|
+
registerCutover("describeTableTool", async (input, apiKey) => {
|
|
15176
|
+
const result = await describeTableTool.execute({ ...input, apiKey }, {});
|
|
15177
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15178
|
+
});
|
|
15179
|
+
registerCutover("listTablesTool", async (input, apiKey) => {
|
|
15180
|
+
const result = await listTablesTool.execute({ ...input, apiKey }, {});
|
|
15181
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15182
|
+
});
|
|
15183
|
+
registerCutover("queryTableTool", async (input, apiKey) => {
|
|
15184
|
+
const result = await queryTableTool.execute({ ...input, apiKey }, {});
|
|
15185
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15186
|
+
});
|
|
15187
|
+
registerCutover("listSharedWithMeTool", async (input, apiKey) => {
|
|
15188
|
+
const result = await listSharedWithMeTool.execute({ ...input, apiKey }, {});
|
|
15189
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15190
|
+
});
|
|
15191
|
+
registerCutover("listVaultsTool", async (input, apiKey) => {
|
|
15192
|
+
const result = await listVaultsTool.execute({ ...input, apiKey }, {});
|
|
15193
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15194
|
+
});
|
|
15195
|
+
registerCutover("videoAnalyzeStatusTool", async (input, apiKey) => {
|
|
15196
|
+
const result = await videoAnalyzeStatusTool.execute({ ...input, apiKey }, {});
|
|
15197
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15198
|
+
});
|
|
15199
|
+
registerCutover("listWebhooksTool", async (input, apiKey) => {
|
|
15200
|
+
const result = await listWebhooksTool.execute({ ...input, apiKey }, {});
|
|
15201
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15202
|
+
});
|
|
15203
|
+
}
|
|
15204
|
+
|
|
15205
|
+
// src/mcp/memory-cutover/writes.ts
|
|
15206
|
+
import { acceptShareTool } from "mcpscraper-memory-tools/tools/access/accept-share";
|
|
15207
|
+
import { approveSenderTool } from "mcpscraper-memory-tools/tools/access/approve-sender";
|
|
15208
|
+
import { declineShareTool } from "mcpscraper-memory-tools/tools/access/decline-share";
|
|
15209
|
+
import { inboxSettingsTool } from "mcpscraper-memory-tools/tools/access/inbox-settings";
|
|
15210
|
+
import { removeApprovedSenderTool } from "mcpscraper-memory-tools/tools/access/remove-approved-sender";
|
|
15211
|
+
import { revokeShareTool } from "mcpscraper-memory-tools/tools/access/revoke-share";
|
|
15212
|
+
import { setAgentIdentityTool } from "mcpscraper-memory-tools/tools/access/set-agent-identity";
|
|
15213
|
+
import { shareNoteTool } from "mcpscraper-memory-tools/tools/access/share-note";
|
|
15214
|
+
import { shareVaultTool } from "mcpscraper-memory-tools/tools/access/share-vault";
|
|
15215
|
+
import { swapVaultTool } from "mcpscraper-memory-tools/tools/access/swap-vault";
|
|
15216
|
+
import { switchAccountTool } from "mcpscraper-memory-tools/tools/access/switch-account";
|
|
15217
|
+
import { unlinkShareTool } from "mcpscraper-memory-tools/tools/access/unlink-share";
|
|
15218
|
+
import { memoryQuestionsTool } from "mcpscraper-memory-tools/tools/capture/memory-questions";
|
|
15219
|
+
import { createChannelTool } from "mcpscraper-memory-tools/tools/channels/create-channel";
|
|
15220
|
+
import { listChannelMessagesTool } from "mcpscraper-memory-tools/tools/channels/list-channel-messages";
|
|
15221
|
+
import { pollChannelTool } from "mcpscraper-memory-tools/tools/channels/poll-channel";
|
|
15222
|
+
import { postMessageTool } from "mcpscraper-memory-tools/tools/channels/post-message";
|
|
15223
|
+
import { reactMessageTool } from "mcpscraper-memory-tools/tools/channels/react-message";
|
|
15224
|
+
import { removeChannelMemberTool } from "mcpscraper-memory-tools/tools/channels/remove-channel-member";
|
|
15225
|
+
import { replyMessageTool } from "mcpscraper-memory-tools/tools/channels/reply-message";
|
|
15226
|
+
import { recordFactTool } from "mcpscraper-memory-tools/tools/facts/record-fact";
|
|
15227
|
+
import { libraryIngestTool } from "mcpscraper-memory-tools/tools/library/library-ingest";
|
|
15228
|
+
import { deleteNoteTool } from "mcpscraper-memory-tools/tools/memory/delete-note";
|
|
15229
|
+
import { putTool } from "mcpscraper-memory-tools/tools/memory/put";
|
|
15230
|
+
import { uploadTool } from "mcpscraper-memory-tools/tools/memory/upload";
|
|
15231
|
+
import { deleteScheduledActionTool } from "mcpscraper-memory-tools/tools/schedule/delete-scheduled-action";
|
|
15232
|
+
import { pauseScheduledActionTool } from "mcpscraper-memory-tools/tools/schedule/pause-scheduled-action";
|
|
15233
|
+
import { resumeScheduledActionTool } from "mcpscraper-memory-tools/tools/schedule/resume-scheduled-action";
|
|
15234
|
+
import { createTableTool } from "mcpscraper-memory-tools/tools/tables/table-create";
|
|
15235
|
+
import { deleteTableRowsTool } from "mcpscraper-memory-tools/tools/tables/table-delete-rows";
|
|
15236
|
+
import { dropTableTool } from "mcpscraper-memory-tools/tools/tables/table-drop";
|
|
15237
|
+
import { insertTableRowsTool } from "mcpscraper-memory-tools/tools/tables/table-insert-rows";
|
|
15238
|
+
import { addVaultTool } from "mcpscraper-memory-tools/tools/vaults/add-vault";
|
|
15239
|
+
import { deleteVaultTool } from "mcpscraper-memory-tools/tools/vaults/delete-vault";
|
|
15240
|
+
var registered2 = false;
|
|
15241
|
+
function registerWriteCutovers() {
|
|
15242
|
+
if (registered2) return;
|
|
15243
|
+
registered2 = true;
|
|
15244
|
+
registerCutover("acceptShareTool", async (input, apiKey) => {
|
|
15245
|
+
const result = await acceptShareTool.execute({ ...input, apiKey }, {});
|
|
15246
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15247
|
+
});
|
|
15248
|
+
registerCutover("approveSenderTool", async (input, apiKey) => {
|
|
15249
|
+
const result = await approveSenderTool.execute({ ...input, apiKey }, {});
|
|
15250
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15251
|
+
});
|
|
15252
|
+
registerCutover("declineShareTool", async (input, apiKey) => {
|
|
15253
|
+
const result = await declineShareTool.execute({ ...input, apiKey }, {});
|
|
15254
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15255
|
+
});
|
|
15256
|
+
registerCutover("inboxSettingsTool", async (input, apiKey) => {
|
|
15257
|
+
const result = await inboxSettingsTool.execute({ ...input, apiKey }, {});
|
|
15258
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15259
|
+
});
|
|
15260
|
+
registerCutover("removeApprovedSenderTool", async (input, apiKey) => {
|
|
15261
|
+
const result = await removeApprovedSenderTool.execute({ ...input, apiKey }, {});
|
|
15262
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15263
|
+
});
|
|
15264
|
+
registerCutover("revokeShareTool", async (input, apiKey) => {
|
|
15265
|
+
const result = await revokeShareTool.execute({ ...input, apiKey }, {});
|
|
15266
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15267
|
+
});
|
|
15268
|
+
registerCutover("setAgentIdentityTool", async (input, apiKey) => {
|
|
15269
|
+
const result = await setAgentIdentityTool.execute({ ...input, apiKey }, {});
|
|
15270
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15271
|
+
});
|
|
15272
|
+
registerCutover("shareNoteTool", async (input, apiKey) => {
|
|
15273
|
+
const result = await shareNoteTool.execute({ ...input, apiKey }, {});
|
|
15274
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15275
|
+
});
|
|
15276
|
+
registerCutover("shareVaultTool", async (input, apiKey) => {
|
|
15277
|
+
const result = await shareVaultTool.execute({ ...input, apiKey }, {});
|
|
15278
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15279
|
+
});
|
|
15280
|
+
registerCutover("swapVaultTool", async (input, apiKey) => {
|
|
15281
|
+
const result = await swapVaultTool.execute({ ...input, apiKey }, {});
|
|
15282
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15283
|
+
});
|
|
15284
|
+
registerCutover("switchAccountTool", async (input, apiKey) => {
|
|
15285
|
+
const result = await switchAccountTool.execute({ ...input, apiKey }, {});
|
|
15286
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15287
|
+
});
|
|
15288
|
+
registerCutover("unlinkShareTool", async (input, apiKey) => {
|
|
15289
|
+
const result = await unlinkShareTool.execute({ ...input, apiKey }, {});
|
|
15290
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15291
|
+
});
|
|
15292
|
+
registerCutover("memoryQuestionsTool", async (input, apiKey) => {
|
|
15293
|
+
const result = await memoryQuestionsTool.execute({ ...input, apiKey }, {});
|
|
15294
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15295
|
+
});
|
|
15296
|
+
registerCutover("createChannelTool", async (input, apiKey) => {
|
|
15297
|
+
const result = await createChannelTool.execute({ ...input, apiKey }, {});
|
|
15298
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15299
|
+
});
|
|
15300
|
+
registerCutover("listChannelMessagesTool", async (input, apiKey) => {
|
|
15301
|
+
const result = await listChannelMessagesTool.execute({ ...input, apiKey }, {});
|
|
15302
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15303
|
+
});
|
|
15304
|
+
registerCutover("pollChannelTool", async (input, apiKey) => {
|
|
15305
|
+
const result = await pollChannelTool.execute({ ...input, apiKey }, {});
|
|
15306
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15307
|
+
});
|
|
15308
|
+
registerCutover("postMessageTool", async (input, apiKey) => {
|
|
15309
|
+
const result = await postMessageTool.execute({ ...input, apiKey }, {});
|
|
15310
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15311
|
+
});
|
|
15312
|
+
registerCutover("reactMessageTool", async (input, apiKey) => {
|
|
15313
|
+
const result = await reactMessageTool.execute({ ...input, apiKey }, {});
|
|
15314
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15315
|
+
});
|
|
15316
|
+
registerCutover("removeChannelMemberTool", async (input, apiKey) => {
|
|
15317
|
+
const result = await removeChannelMemberTool.execute({ ...input, apiKey }, {});
|
|
15318
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15319
|
+
});
|
|
15320
|
+
registerCutover("replyMessageTool", async (input, apiKey) => {
|
|
15321
|
+
const result = await replyMessageTool.execute({ ...input, apiKey }, {});
|
|
15322
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15323
|
+
});
|
|
15324
|
+
registerCutover("recordFactTool", async (input, apiKey) => {
|
|
15325
|
+
const result = await recordFactTool.execute({ ...input, apiKey }, {});
|
|
15326
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15327
|
+
});
|
|
15328
|
+
registerCutover("libraryIngestTool", async (input, apiKey) => {
|
|
15329
|
+
const result = await libraryIngestTool.execute({ ...input, apiKey }, {});
|
|
15330
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15331
|
+
});
|
|
15332
|
+
registerCutover("deleteNoteTool", async (input, apiKey) => {
|
|
15333
|
+
const result = await deleteNoteTool.execute({ ...input, apiKey }, {});
|
|
15334
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15335
|
+
});
|
|
15336
|
+
registerCutover("putTool", async (input, apiKey) => {
|
|
15337
|
+
const result = await putTool.execute({ ...input, apiKey }, {});
|
|
15338
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15339
|
+
});
|
|
15340
|
+
registerCutover("uploadTool", async (input, apiKey) => {
|
|
15341
|
+
const result = await uploadTool.execute({ ...input, apiKey }, {});
|
|
15342
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15343
|
+
});
|
|
15344
|
+
registerCutover("deleteScheduledActionTool", async (input, apiKey) => {
|
|
15345
|
+
const result = await deleteScheduledActionTool.execute({ ...input, apiKey }, {});
|
|
15346
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15347
|
+
});
|
|
15348
|
+
registerCutover("pauseScheduledActionTool", async (input, apiKey) => {
|
|
15349
|
+
const result = await pauseScheduledActionTool.execute({ ...input, apiKey }, {});
|
|
15350
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15351
|
+
});
|
|
15352
|
+
registerCutover("resumeScheduledActionTool", async (input, apiKey) => {
|
|
15353
|
+
const result = await resumeScheduledActionTool.execute({ ...input, apiKey }, {});
|
|
15354
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15355
|
+
});
|
|
15356
|
+
registerCutover("createTableTool", async (input, apiKey) => {
|
|
15357
|
+
const result = await createTableTool.execute({ ...input, apiKey }, {});
|
|
15358
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15359
|
+
});
|
|
15360
|
+
registerCutover("deleteTableRowsTool", async (input, apiKey) => {
|
|
15361
|
+
const result = await deleteTableRowsTool.execute({ ...input, apiKey }, {});
|
|
15362
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15363
|
+
});
|
|
15364
|
+
registerCutover("dropTableTool", async (input, apiKey) => {
|
|
15365
|
+
const result = await dropTableTool.execute({ ...input, apiKey }, {});
|
|
15366
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15367
|
+
});
|
|
15368
|
+
registerCutover("insertTableRowsTool", async (input, apiKey) => {
|
|
15369
|
+
const result = await insertTableRowsTool.execute({ ...input, apiKey }, {});
|
|
15370
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15371
|
+
});
|
|
15372
|
+
registerCutover("addVaultTool", async (input, apiKey) => {
|
|
15373
|
+
const result = await addVaultTool.execute({ ...input, apiKey }, {});
|
|
15374
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15375
|
+
});
|
|
15376
|
+
registerCutover("deleteVaultTool", async (input, apiKey) => {
|
|
15377
|
+
const result = await deleteVaultTool.execute({ ...input, apiKey }, {});
|
|
15378
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15379
|
+
});
|
|
15380
|
+
}
|
|
15381
|
+
|
|
15382
|
+
// src/mcp/memory-cutover/billing.ts
|
|
15383
|
+
import { issueKeyTool } from "mcpscraper-memory-tools/tools/access/issue-key";
|
|
15384
|
+
import { listKeysTool } from "mcpscraper-memory-tools/tools/access/list-keys";
|
|
15385
|
+
import { revokeKeyTool } from "mcpscraper-memory-tools/tools/access/revoke-key";
|
|
15386
|
+
import { setScopeTool } from "mcpscraper-memory-tools/tools/access/set-scope";
|
|
15387
|
+
import { inviteAccountTool } from "mcpscraper-memory-tools/tools/access/invite-account";
|
|
15388
|
+
import { getChatLinkTool } from "mcpscraper-memory-tools/tools/access/get-chat-link";
|
|
15389
|
+
import { revokeChatLinkTool } from "mcpscraper-memory-tools/tools/access/revoke-chat-link";
|
|
15390
|
+
import { provisionDefaultsTool as provisionDefaultsTool2 } from "mcpscraper-memory-tools/tools/vaults/provision-defaults";
|
|
15391
|
+
import { createSecureVaultTool } from "mcpscraper-memory-tools/tools/vaults/create-secure-vault";
|
|
15392
|
+
import { createScheduledActionTool } from "mcpscraper-memory-tools/tools/schedule/create-scheduled-action";
|
|
15393
|
+
import { getScheduleStatusTool } from "mcpscraper-memory-tools/tools/schedule/get-schedule-status";
|
|
15394
|
+
import { getScheduleLinkTool } from "mcpscraper-memory-tools/tools/schedule/get-schedule-link";
|
|
15395
|
+
import { revokeScheduleLinkTool } from "mcpscraper-memory-tools/tools/schedule/revoke-schedule-link";
|
|
15396
|
+
import { setScheduleEntitlementTool as setScheduleEntitlementTool2 } from "mcpscraper-memory-tools/tools/schedule/set-schedule-entitlement";
|
|
15397
|
+
import { createWebhookTool } from "mcpscraper-memory-tools/tools/webhooks/create-webhook";
|
|
15398
|
+
import { revokeWebhookTool } from "mcpscraper-memory-tools/tools/webhooks/revoke-webhook";
|
|
15399
|
+
var registered3 = false;
|
|
15400
|
+
function registerBillingCutovers() {
|
|
15401
|
+
if (registered3) return;
|
|
15402
|
+
registered3 = true;
|
|
15403
|
+
registerCutover("issueKeyTool", async (input, apiKey) => {
|
|
15404
|
+
const result = await issueKeyTool.execute({ ...input, apiKey }, {});
|
|
15405
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15406
|
+
});
|
|
15407
|
+
registerCutover("listKeysTool", async (input, apiKey) => {
|
|
15408
|
+
const result = await listKeysTool.execute({ ...input, apiKey }, {});
|
|
15409
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15410
|
+
});
|
|
15411
|
+
registerCutover("revokeKeyTool", async (input, apiKey) => {
|
|
15412
|
+
const result = await revokeKeyTool.execute({ ...input, apiKey }, {});
|
|
15413
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15414
|
+
});
|
|
15415
|
+
registerCutover("setScopeTool", async (input, apiKey) => {
|
|
15416
|
+
const result = await setScopeTool.execute({ ...input, apiKey }, {});
|
|
15417
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15418
|
+
});
|
|
15419
|
+
registerCutover("inviteAccountTool", async (input, apiKey) => {
|
|
15420
|
+
const result = await inviteAccountTool.execute({ ...input, apiKey }, {});
|
|
15421
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15422
|
+
});
|
|
15423
|
+
registerCutover("getChatLinkTool", async (input, apiKey) => {
|
|
15424
|
+
const result = await getChatLinkTool.execute({ ...input, apiKey }, {});
|
|
15425
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15426
|
+
});
|
|
15427
|
+
registerCutover("revokeChatLinkTool", async (input, apiKey) => {
|
|
15428
|
+
const result = await revokeChatLinkTool.execute({ ...input, apiKey }, {});
|
|
15429
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15430
|
+
});
|
|
15431
|
+
registerCutover("provisionDefaultsTool", async (input, apiKey) => {
|
|
15432
|
+
const result = await provisionDefaultsTool2.execute({ ...input, apiKey }, {});
|
|
15433
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15434
|
+
});
|
|
15435
|
+
registerCutover("createSecureVaultTool", async (input, apiKey) => {
|
|
15436
|
+
const result = await createSecureVaultTool.execute({ ...input, apiKey }, {});
|
|
15437
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15438
|
+
});
|
|
15439
|
+
registerCutover("createScheduledActionTool", async (input, apiKey) => {
|
|
15440
|
+
const result = await createScheduledActionTool.execute({ ...input, apiKey }, {});
|
|
15441
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15442
|
+
});
|
|
15443
|
+
registerCutover("getScheduleStatusTool", async (input, apiKey) => {
|
|
15444
|
+
const result = await getScheduleStatusTool.execute({ ...input, apiKey }, {});
|
|
15445
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15446
|
+
});
|
|
15447
|
+
registerCutover("getScheduleLinkTool", async (input, apiKey) => {
|
|
15448
|
+
const result = await getScheduleLinkTool.execute({ ...input, apiKey }, {});
|
|
15449
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15450
|
+
});
|
|
15451
|
+
registerCutover("revokeScheduleLinkTool", async (input, apiKey) => {
|
|
15452
|
+
const result = await revokeScheduleLinkTool.execute({ ...input, apiKey }, {});
|
|
15453
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15454
|
+
});
|
|
15455
|
+
registerCutover("setScheduleEntitlementTool", async (input, apiKey) => {
|
|
15456
|
+
const result = await setScheduleEntitlementTool2.execute({ ...input, apiKey }, {});
|
|
15457
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15458
|
+
});
|
|
15459
|
+
registerCutover("createWebhookTool", async (input, apiKey) => {
|
|
15460
|
+
const result = await createWebhookTool.execute({ ...input, apiKey }, {});
|
|
15461
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15462
|
+
});
|
|
15463
|
+
registerCutover("revokeWebhookTool", async (input, apiKey) => {
|
|
15464
|
+
const result = await revokeWebhookTool.execute({ ...input, apiKey }, {});
|
|
15465
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15466
|
+
});
|
|
15467
|
+
}
|
|
15468
|
+
|
|
15469
|
+
// src/mcp/memory-cutover/cross-service.ts
|
|
15470
|
+
import { proposeScheduledActionTool } from "mcpscraper-memory-tools/tools/schedule/propose-scheduled-action";
|
|
15471
|
+
var registered4 = false;
|
|
15472
|
+
function registerCrossServiceCutovers() {
|
|
15473
|
+
if (registered4) return;
|
|
15474
|
+
registered4 = true;
|
|
15475
|
+
registerCutover("proposeScheduledActionTool", async (input, apiKey) => {
|
|
15476
|
+
const result = await proposeScheduledActionTool.execute({ ...input, apiKey }, {});
|
|
15477
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15478
|
+
});
|
|
15479
|
+
}
|
|
15480
|
+
|
|
15481
|
+
// src/mcp/memory-cutover/video.ts
|
|
15482
|
+
import { videoAnalyzeStartTool } from "mcpscraper-memory-tools/tools/video/start";
|
|
15483
|
+
var registered5 = false;
|
|
15484
|
+
function registerVideoCutovers() {
|
|
15485
|
+
if (registered5) return;
|
|
15486
|
+
registered5 = true;
|
|
15487
|
+
registerCutover("videoAnalyzeStartTool", async (input, apiKey) => {
|
|
15488
|
+
const result = await videoAnalyzeStartTool.execute({ ...input, apiKey }, {});
|
|
15489
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
15490
|
+
});
|
|
15491
|
+
}
|
|
15492
|
+
|
|
14911
15493
|
// src/mcp/mcp-oauth.ts
|
|
14912
15494
|
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
14913
15495
|
function oauthIssuer() {
|
|
@@ -14948,6 +15530,11 @@ async function verifyScraperOAuthJwt(token) {
|
|
|
14948
15530
|
}
|
|
14949
15531
|
|
|
14950
15532
|
// src/mcp/mcp-routes.ts
|
|
15533
|
+
registerReadCutovers();
|
|
15534
|
+
registerWriteCutovers();
|
|
15535
|
+
registerBillingCutovers();
|
|
15536
|
+
registerCrossServiceCutovers();
|
|
15537
|
+
registerVideoCutovers();
|
|
14951
15538
|
configureReportSaving(false);
|
|
14952
15539
|
function mcpAuthError(message = "authentication required") {
|
|
14953
15540
|
const body = JSON.stringify({
|
|
@@ -14981,20 +15568,20 @@ async function requireMcpCallerKey(c) {
|
|
|
14981
15568
|
if (!identity) return mcpAuthError("Bearer token has no subject");
|
|
14982
15569
|
const user2 = await getUserByEmail(identity);
|
|
14983
15570
|
if (!user2 || !user2.api_key || user2.key_active !== 1) return mcpAuthError("No active MCP Scraper account for this identity");
|
|
14984
|
-
return user2.api_key;
|
|
15571
|
+
return { key: user2.api_key, user: user2 };
|
|
14985
15572
|
}
|
|
14986
15573
|
const callerKey = xApiKey ?? bearerToken;
|
|
14987
15574
|
if (!callerKey) return mcpAuthError();
|
|
14988
15575
|
const user = await getUserByApiKey(callerKey);
|
|
14989
15576
|
if (!user) return mcpAuthError();
|
|
14990
|
-
return callerKey;
|
|
15577
|
+
return { key: callerKey, user };
|
|
14991
15578
|
}
|
|
14992
15579
|
var mcpApp = new Hono14();
|
|
14993
15580
|
mcpApp.all("/", async (c) => {
|
|
14994
15581
|
try {
|
|
14995
15582
|
const keyOrError = await requireMcpCallerKey(c);
|
|
14996
15583
|
if (keyOrError instanceof Response) return keyOrError;
|
|
14997
|
-
const callerKey = keyOrError;
|
|
15584
|
+
const { key: callerKey, user } = keyOrError;
|
|
14998
15585
|
const baseUrl = process.env.MCP_SCRAPER_BASE_URL?.trim() ?? process.env.MCP_BASE_URL?.trim() ?? "https://mcpscraper.dev";
|
|
14999
15586
|
const executor = new HttpMcpToolExecutor(baseUrl, callerKey);
|
|
15000
15587
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
@@ -15005,7 +15592,8 @@ mcpApp.all("/", async (c) => {
|
|
|
15005
15592
|
const server = buildPaaExtractorMcpServer(executor, { savesReportsLocally: false, ownerId: hashOwnerId(callerKey) });
|
|
15006
15593
|
registerSerpIntelligenceCaptureTools(server, executor);
|
|
15007
15594
|
registerBrowserAgentMcpTools(server, { baseUrl, apiKey: callerKey, consoleBaseUrl, savesReportsLocally: false });
|
|
15008
|
-
|
|
15595
|
+
const memoryExecutor = new HybridMemoryToolExecutor(new MemoryMcpToolExecutor(baseUrl, callerKey), user);
|
|
15596
|
+
registerMemoryMcpTools(server, memoryExecutor);
|
|
15009
15597
|
await server.connect(transport);
|
|
15010
15598
|
return transport.handleRequest(c.req.raw);
|
|
15011
15599
|
} catch {
|
|
@@ -15093,23 +15681,34 @@ async function migrateBrowserAgent() {
|
|
|
15093
15681
|
await db.execute(`ALTER TABLE browser_auth_connections ADD COLUMN updated_at TEXT`);
|
|
15094
15682
|
} catch {
|
|
15095
15683
|
}
|
|
15684
|
+
try {
|
|
15685
|
+
await db.execute(`ALTER TABLE browser_auth_connections ADD COLUMN status TEXT NOT NULL DEFAULT 'NEEDS_AUTH'`);
|
|
15686
|
+
} catch {
|
|
15687
|
+
}
|
|
15688
|
+
try {
|
|
15689
|
+
await db.execute(`ALTER TABLE browser_auth_connections ADD COLUMN browser_agent_session_id TEXT`);
|
|
15690
|
+
} catch {
|
|
15691
|
+
}
|
|
15096
15692
|
await db.execute(`CREATE INDEX IF NOT EXISTS browser_auth_connections_profile ON browser_auth_connections(profile)`);
|
|
15097
15693
|
_ready = true;
|
|
15098
15694
|
}
|
|
15099
|
-
async function
|
|
15100
|
-
|
|
15695
|
+
async function createAuthConnectionRow(input) {
|
|
15696
|
+
const db = getDb();
|
|
15697
|
+
const connectionId = `authc_${randomUUID2().replace(/-/g, "").slice(0, 20)}`;
|
|
15698
|
+
await db.execute({
|
|
15699
|
+
sql: `INSERT INTO browser_auth_connections (connection_id, domain, profile, account_email, note, status, browser_agent_session_id)
|
|
15700
|
+
VALUES (?, ?, ?, ?, ?, 'NEEDS_AUTH', ?)`,
|
|
15701
|
+
args: [connectionId, input.domain, input.profile, input.accountEmail, input.note, input.browserAgentSessionId]
|
|
15702
|
+
});
|
|
15703
|
+
const row = await getAuthConnectionRow(connectionId);
|
|
15704
|
+
if (!row) throw new Error("auth connection insert failed");
|
|
15705
|
+
return row;
|
|
15706
|
+
}
|
|
15707
|
+
async function markAuthConnectionAuthenticated(connectionId) {
|
|
15101
15708
|
const db = getDb();
|
|
15102
15709
|
await db.execute({
|
|
15103
|
-
sql: `
|
|
15104
|
-
|
|
15105
|
-
ON CONFLICT(connection_id) DO UPDATE SET
|
|
15106
|
-
hosted_url = COALESCE(excluded.hosted_url, browser_auth_connections.hosted_url),
|
|
15107
|
-
domain = COALESCE(excluded.domain, browser_auth_connections.domain),
|
|
15108
|
-
profile = COALESCE(excluded.profile, browser_auth_connections.profile),
|
|
15109
|
-
account_email = COALESCE(excluded.account_email, browser_auth_connections.account_email),
|
|
15110
|
-
note = COALESCE(excluded.note, browser_auth_connections.note),
|
|
15111
|
-
updated_at = datetime('now')`,
|
|
15112
|
-
args: [input.connectionId, input.hostedUrl, input.domain, input.profile, input.accountEmail ?? null, input.note ?? null]
|
|
15710
|
+
sql: `UPDATE browser_auth_connections SET status = 'AUTHENTICATED', updated_at = datetime('now') WHERE connection_id = ?`,
|
|
15711
|
+
args: [connectionId]
|
|
15113
15712
|
});
|
|
15114
15713
|
}
|
|
15115
15714
|
async function getAuthConnectionRow(connectionId) {
|
|
@@ -15956,79 +16555,10 @@ async function ensureProfile(k, name) {
|
|
|
15956
16555
|
if (!isProfileConflict(err)) throw err;
|
|
15957
16556
|
}
|
|
15958
16557
|
}
|
|
15959
|
-
function profileConnectionMatches(connection, profileName, domain) {
|
|
15960
|
-
if (!connection || typeof connection !== "object") return false;
|
|
15961
|
-
const data = connection;
|
|
15962
|
-
return data.profile_name === profileName && data.domain === domain;
|
|
15963
|
-
}
|
|
15964
|
-
async function findProfileConnection(k, profileName, domain) {
|
|
15965
|
-
for await (const connection of k.auth.connections.list({ profile_name: profileName, domain })) {
|
|
15966
|
-
if (profileConnectionMatches(connection, profileName, domain)) return connection;
|
|
15967
|
-
}
|
|
15968
|
-
return null;
|
|
15969
|
-
}
|
|
15970
|
-
async function listProfileConnections(profileName) {
|
|
15971
|
-
if (!profileName) return [];
|
|
15972
|
-
const k = client();
|
|
15973
|
-
const out = [];
|
|
15974
|
-
for await (const connection of k.auth.connections.list({ profile_name: profileName })) {
|
|
15975
|
-
const data = connection;
|
|
15976
|
-
if (data.profile_name && data.profile_name !== profileName) continue;
|
|
15977
|
-
out.push(profileOnboardResult(connection));
|
|
15978
|
-
}
|
|
15979
|
-
return out;
|
|
15980
|
-
}
|
|
15981
|
-
async function findOrCreateProfileConnection(k, opts) {
|
|
15982
|
-
try {
|
|
15983
|
-
return await k.auth.connections.create({
|
|
15984
|
-
domain: opts.domain,
|
|
15985
|
-
profile_name: opts.profileName,
|
|
15986
|
-
...opts.loginUrl ? { login_url: opts.loginUrl } : {}
|
|
15987
|
-
});
|
|
15988
|
-
} catch (err) {
|
|
15989
|
-
if (!isProfileConflict(err)) throw err;
|
|
15990
|
-
const existing = await findProfileConnection(k, opts.profileName, opts.domain);
|
|
15991
|
-
if (existing) return existing;
|
|
15992
|
-
throw err;
|
|
15993
|
-
}
|
|
15994
|
-
}
|
|
15995
|
-
function profileOnboardResult(connection, hostedUrl = null, liveViewUrl = null) {
|
|
15996
|
-
return {
|
|
15997
|
-
connectionId: String(connection.id),
|
|
15998
|
-
profileName: String(connection.profile_name),
|
|
15999
|
-
domain: String(connection.domain),
|
|
16000
|
-
status: String(connection.status),
|
|
16001
|
-
flowStatus: typeof connection.flow_status === "string" ? connection.flow_status : null,
|
|
16002
|
-
flowStep: typeof connection.flow_step === "string" ? connection.flow_step : null,
|
|
16003
|
-
flowExpiresAt: typeof connection.flow_expires_at === "string" ? connection.flow_expires_at : null,
|
|
16004
|
-
hostedUrl: hostedUrl ?? (typeof connection.hosted_url === "string" ? connection.hosted_url : null),
|
|
16005
|
-
liveViewUrl: liveViewUrl ?? (typeof connection.live_view_url === "string" ? connection.live_view_url : null),
|
|
16006
|
-
browserSessionId: typeof connection.browser_session_id === "string" ? connection.browser_session_id : null,
|
|
16007
|
-
postLoginUrl: typeof connection.post_login_url === "string" ? connection.post_login_url : null
|
|
16008
|
-
};
|
|
16009
|
-
}
|
|
16010
16558
|
function explicitProxyId(value) {
|
|
16011
16559
|
const trimmed = value?.trim();
|
|
16012
16560
|
return trimmed || void 0;
|
|
16013
16561
|
}
|
|
16014
|
-
async function startProfileOnboarding(opts) {
|
|
16015
|
-
const k = client();
|
|
16016
|
-
const connection = await findOrCreateProfileConnection(k, opts);
|
|
16017
|
-
const login = await k.auth.connections.login(connection.id);
|
|
16018
|
-
const state = await k.auth.connections.retrieve(connection.id);
|
|
16019
|
-
return profileOnboardResult(state, login.hosted_url ?? null, login.live_view_url ?? null);
|
|
16020
|
-
}
|
|
16021
|
-
async function getProfileOnboardingStatus(input) {
|
|
16022
|
-
const k = client();
|
|
16023
|
-
let connection = null;
|
|
16024
|
-
if (input.connectionId) {
|
|
16025
|
-
connection = await k.auth.connections.retrieve(input.connectionId);
|
|
16026
|
-
} else if (input.profileName && input.domain) {
|
|
16027
|
-
connection = await findProfileConnection(k, input.profileName, input.domain);
|
|
16028
|
-
}
|
|
16029
|
-
if (!connection) throw new Error("profile auth connection not found");
|
|
16030
|
-
return profileOnboardResult(connection);
|
|
16031
|
-
}
|
|
16032
16562
|
async function createSession(opts = {}) {
|
|
16033
16563
|
const k = client();
|
|
16034
16564
|
const resolvedProxyId = explicitProxyId(opts.proxyId);
|
|
@@ -16370,24 +16900,39 @@ async function charge(sessionId, userId, _startedAtMs) {
|
|
|
16370
16900
|
if (res.ok) await setBilledMc(sessionId, owed);
|
|
16371
16901
|
}
|
|
16372
16902
|
}
|
|
16903
|
+
async function closeAndSettleSession(row) {
|
|
16904
|
+
if (row.user_id != null) {
|
|
16905
|
+
try {
|
|
16906
|
+
await charge(row.id, row.user_id);
|
|
16907
|
+
} catch {
|
|
16908
|
+
}
|
|
16909
|
+
}
|
|
16910
|
+
try {
|
|
16911
|
+
await closeSession(row.runtime_session_id);
|
|
16912
|
+
} catch {
|
|
16913
|
+
}
|
|
16914
|
+
await markSessionClosed(row.id).catch(() => {
|
|
16915
|
+
});
|
|
16916
|
+
await releaseConcurrencyGate(row.concurrency_lock_id).catch(() => {
|
|
16917
|
+
});
|
|
16918
|
+
}
|
|
16919
|
+
async function completeAuthConnection(connectionId) {
|
|
16920
|
+
const connection = await getAuthConnectionRow(connectionId);
|
|
16921
|
+
if (!connection) return { ok: false, error: "not found" };
|
|
16922
|
+
if (connection.browser_agent_session_id) {
|
|
16923
|
+
const sessionRow = await getSessionRow(connection.browser_agent_session_id);
|
|
16924
|
+
if (sessionRow && sessionRow.status === "open") {
|
|
16925
|
+
await closeAndSettleSession(sessionRow);
|
|
16926
|
+
}
|
|
16927
|
+
}
|
|
16928
|
+
await markAuthConnectionAuthenticated(connectionId);
|
|
16929
|
+
return { ok: true };
|
|
16930
|
+
}
|
|
16373
16931
|
async function reapIdleBrowserSessions(idleSeconds = 120) {
|
|
16374
16932
|
const rows = await listIdleOpenSessionRows(idleSeconds);
|
|
16375
16933
|
let reaped = 0;
|
|
16376
16934
|
for (const row of rows) {
|
|
16377
|
-
|
|
16378
|
-
try {
|
|
16379
|
-
await charge(row.id, row.user_id);
|
|
16380
|
-
} catch {
|
|
16381
|
-
}
|
|
16382
|
-
}
|
|
16383
|
-
try {
|
|
16384
|
-
await closeSession(row.runtime_session_id);
|
|
16385
|
-
} catch {
|
|
16386
|
-
}
|
|
16387
|
-
await markSessionClosed(row.id).catch(() => {
|
|
16388
|
-
});
|
|
16389
|
-
if (row.concurrency_lock_id) await releaseConcurrencyGate(row.concurrency_lock_id).catch(() => {
|
|
16390
|
-
});
|
|
16935
|
+
await closeAndSettleSession(row);
|
|
16391
16936
|
reaped++;
|
|
16392
16937
|
}
|
|
16393
16938
|
return { reaped };
|
|
@@ -16455,74 +17000,87 @@ function buildBrowserAgentRoutes() {
|
|
|
16455
17000
|
});
|
|
16456
17001
|
app2.use("*", auth);
|
|
16457
17002
|
app2.post("/profiles/onboard", async (c) => {
|
|
17003
|
+
const user = c.get("user");
|
|
17004
|
+
if (Number(user.balance_mc ?? 0) < BROWSER_OPEN_MIN_BALANCE_MC) {
|
|
17005
|
+
return c.json(insufficientBalanceResponse(Number(user.balance_mc ?? 0), BROWSER_OPEN_MIN_BALANCE_MC), 402);
|
|
17006
|
+
}
|
|
16458
17007
|
const body = await c.req.json().catch(() => ({}));
|
|
16459
17008
|
const profileName = typeof body.profile === "string" ? body.profile.trim() : "";
|
|
16460
17009
|
const domain = typeof body.domain === "string" ? body.domain.trim().replace(/^https?:\/\//, "").replace(/\/.*$/, "") : "chatgpt.com";
|
|
16461
17010
|
const loginUrl = typeof body.login_url === "string" ? body.login_url.trim() : void 0;
|
|
16462
17011
|
const accountEmail = typeof body.account_email === "string" ? body.account_email.trim() || null : null;
|
|
16463
17012
|
const note = typeof body.note === "string" ? body.note.trim() || null : null;
|
|
17013
|
+
const timeoutSeconds = typeof body.timeout_seconds === "number" ? body.timeout_seconds : void 0;
|
|
16464
17014
|
if (!profileName) return c.json({ error: "profile is required" }, 400);
|
|
16465
17015
|
if (!domain) return c.json({ error: "domain is required" }, 400);
|
|
17016
|
+
const gate = await acquireConcurrencyGate(user, "browser_agent_session", {
|
|
17017
|
+
ttlSeconds: browserSessionLockTtlSeconds(timeoutSeconds),
|
|
17018
|
+
metadata: { label: typeof body.label === "string" ? body.label : null }
|
|
17019
|
+
});
|
|
17020
|
+
if (!gate.ok) return c.json(concurrencyLimitExceededResponse(gate), 429, { "Retry-After": String(gate.retryAfterSeconds) });
|
|
17021
|
+
let runtimeSessionId = null;
|
|
16466
17022
|
try {
|
|
16467
|
-
const
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
|
|
16473
|
-
|
|
16474
|
-
|
|
16475
|
-
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
|
|
17023
|
+
const created = await createSession({
|
|
17024
|
+
timeoutSeconds,
|
|
17025
|
+
profileName,
|
|
17026
|
+
saveProfileChanges: true,
|
|
17027
|
+
startUrl: loginUrl || `https://${domain}/`,
|
|
17028
|
+
disableDefaultProxy: true
|
|
17029
|
+
});
|
|
17030
|
+
runtimeSessionId = created.runtimeSessionId;
|
|
17031
|
+
const sessionRow = await createSessionRow({
|
|
17032
|
+
runtimeSessionId: created.runtimeSessionId,
|
|
17033
|
+
liveViewUrl: created.liveViewUrl,
|
|
17034
|
+
cdpWsUrl: created.cdpWsUrl,
|
|
17035
|
+
label: typeof body.label === "string" ? body.label : `Login setup: ${domain} \u2192 ${profileName}`,
|
|
17036
|
+
userId: user.id,
|
|
17037
|
+
concurrencyLockId: gate.lockId
|
|
17038
|
+
});
|
|
17039
|
+
const connection = await createAuthConnectionRow({
|
|
17040
|
+
domain,
|
|
17041
|
+
profile: profileName,
|
|
17042
|
+
accountEmail,
|
|
17043
|
+
note,
|
|
17044
|
+
browserAgentSessionId: sessionRow.id
|
|
17045
|
+
});
|
|
16479
17046
|
return c.json({
|
|
16480
|
-
connection_id:
|
|
16481
|
-
profile:
|
|
16482
|
-
domain
|
|
16483
|
-
status:
|
|
16484
|
-
|
|
16485
|
-
flow_step: result.flowStep,
|
|
16486
|
-
flow_expires_at: result.flowExpiresAt,
|
|
16487
|
-
browser_session_id: result.browserSessionId,
|
|
16488
|
-
post_login_url: result.postLoginUrl
|
|
17047
|
+
connection_id: connection.connection_id,
|
|
17048
|
+
profile: profileName,
|
|
17049
|
+
domain,
|
|
17050
|
+
status: connection.status,
|
|
17051
|
+
browser_session_id: sessionRow.id
|
|
16489
17052
|
});
|
|
16490
17053
|
} catch (err) {
|
|
17054
|
+
if (runtimeSessionId) {
|
|
17055
|
+
try {
|
|
17056
|
+
await closeSession(runtimeSessionId);
|
|
17057
|
+
} catch {
|
|
17058
|
+
}
|
|
17059
|
+
}
|
|
17060
|
+
await releaseConcurrencyGate(gate.lockId);
|
|
16491
17061
|
return c.json(failure(err), 502);
|
|
16492
17062
|
}
|
|
16493
17063
|
});
|
|
16494
17064
|
app2.post("/profiles/status", async (c) => {
|
|
16495
17065
|
const body = await c.req.json().catch(() => ({}));
|
|
16496
|
-
const connectionId = typeof body.connection_id === "string" ? body.connection_id.trim() :
|
|
16497
|
-
const profileName = typeof body.profile === "string" ? body.profile.trim() :
|
|
17066
|
+
const connectionId = typeof body.connection_id === "string" ? body.connection_id.trim() : "";
|
|
17067
|
+
const profileName = typeof body.profile === "string" ? body.profile.trim() : "";
|
|
16498
17068
|
const domain = typeof body.domain === "string" ? body.domain.trim().replace(/^https?:\/\//, "").replace(/\/.*$/, "") : void 0;
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16507
|
-
|
|
16508
|
-
|
|
16509
|
-
|
|
16510
|
-
|
|
16511
|
-
|
|
16512
|
-
|
|
16513
|
-
|
|
16514
|
-
profile: result.profileName,
|
|
16515
|
-
domain: result.domain,
|
|
16516
|
-
status: result.status,
|
|
16517
|
-
flow_status: result.flowStatus,
|
|
16518
|
-
flow_step: result.flowStep,
|
|
16519
|
-
flow_expires_at: result.flowExpiresAt,
|
|
16520
|
-
browser_session_id: result.browserSessionId,
|
|
16521
|
-
post_login_url: result.postLoginUrl
|
|
16522
|
-
});
|
|
16523
|
-
} catch (err) {
|
|
16524
|
-
return c.json(failure(err), 404);
|
|
16525
|
-
}
|
|
17069
|
+
let row = null;
|
|
17070
|
+
if (connectionId) {
|
|
17071
|
+
row = await getAuthConnectionRow(connectionId);
|
|
17072
|
+
} else if (profileName && domain) {
|
|
17073
|
+
const rows = await listAuthConnectionsByProfile(profileName);
|
|
17074
|
+
row = rows.find((r) => r.domain === domain) ?? null;
|
|
17075
|
+
}
|
|
17076
|
+
if (!row) return c.json({ error: "auth connection not found" }, 404);
|
|
17077
|
+
return c.json({
|
|
17078
|
+
connection_id: row.connection_id,
|
|
17079
|
+
profile: row.profile,
|
|
17080
|
+
domain: row.domain,
|
|
17081
|
+
status: row.status,
|
|
17082
|
+
browser_session_id: row.browser_agent_session_id
|
|
17083
|
+
});
|
|
16526
17084
|
});
|
|
16527
17085
|
app2.post("/profiles/list", async (c) => {
|
|
16528
17086
|
const body = await c.req.json().catch(() => ({}));
|
|
@@ -16531,23 +17089,15 @@ function buildBrowserAgentRoutes() {
|
|
|
16531
17089
|
const domainFilter = typeof body.domain === "string" ? body.domain.trim().replace(/^https?:\/\//, "").replace(/\/.*$/, "") : void 0;
|
|
16532
17090
|
const connectionIdFilter = typeof body.connection_id === "string" ? body.connection_id.trim() : void 0;
|
|
16533
17091
|
try {
|
|
16534
|
-
const
|
|
16535
|
-
|
|
16536
|
-
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
|
|
16542
|
-
|
|
16543
|
-
connection_id: conn.connectionId,
|
|
16544
|
-
domain: conn.domain,
|
|
16545
|
-
status: conn.status,
|
|
16546
|
-
account_email: record?.account_email ?? null,
|
|
16547
|
-
note: record?.note ?? null,
|
|
16548
|
-
last_connected_at: record?.updated_at ?? record?.created_at ?? null
|
|
16549
|
-
};
|
|
16550
|
-
});
|
|
17092
|
+
const stored = await listAuthConnectionsByProfile(profileName);
|
|
17093
|
+
let connections = stored.map((row) => ({
|
|
17094
|
+
connection_id: row.connection_id,
|
|
17095
|
+
domain: row.domain,
|
|
17096
|
+
status: row.status,
|
|
17097
|
+
account_email: row.account_email,
|
|
17098
|
+
note: row.note,
|
|
17099
|
+
last_connected_at: row.updated_at ?? row.created_at
|
|
17100
|
+
}));
|
|
16551
17101
|
if (connectionIdFilter) connections = connections.filter((c2) => c2.connection_id === connectionIdFilter);
|
|
16552
17102
|
if (domainFilter) connections = connections.filter((c2) => c2.domain === domainFilter);
|
|
16553
17103
|
return c.json({ profile: profileName, connections });
|
|
@@ -16622,13 +17172,7 @@ function buildBrowserAgentRoutes() {
|
|
|
16622
17172
|
const user = c.get("user");
|
|
16623
17173
|
const row = await loadOpenSession(c.req.param("id"), user.id);
|
|
16624
17174
|
if (!row) return c.json({ error: "not found" }, 404);
|
|
16625
|
-
await
|
|
16626
|
-
try {
|
|
16627
|
-
await closeSession(row.runtime_session_id);
|
|
16628
|
-
} catch {
|
|
16629
|
-
}
|
|
16630
|
-
await markSessionClosed(row.id);
|
|
16631
|
-
await releaseConcurrencyGate(row.concurrency_lock_id);
|
|
17175
|
+
await closeAndSettleSession(row);
|
|
16632
17176
|
return c.json({ ok: true });
|
|
16633
17177
|
});
|
|
16634
17178
|
app2.post("/sessions/:id/goto", async (c) => {
|
|
@@ -16912,17 +17456,30 @@ function buildBrowserAgentRoutes() {
|
|
|
16912
17456
|
}
|
|
16913
17457
|
|
|
16914
17458
|
// src/api/browser-agent-console.ts
|
|
16915
|
-
function renderAuthConsoleHtml(connectionId,
|
|
16916
|
-
const
|
|
16917
|
-
const
|
|
16918
|
-
const
|
|
16919
|
-
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
17459
|
+
function renderAuthConsoleHtml(connectionId, info) {
|
|
17460
|
+
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
17461
|
+
const safeId = esc(connectionId);
|
|
17462
|
+
const domainLabel = info.domain ? esc(info.domain) : "this site";
|
|
17463
|
+
let body;
|
|
17464
|
+
if (info.status === "AUTHENTICATED") {
|
|
17465
|
+
body = `<div class="empty">
|
|
17466
|
+
<div class="check">\u2713</div>
|
|
17467
|
+
<div>You're signed in to ${domainLabel}.</div>
|
|
17468
|
+
<div class="muted">This login is saved. You can close this tab.</div>
|
|
17469
|
+
</div>`;
|
|
17470
|
+
} else if (info.sessionOpen && info.liveViewUrl) {
|
|
17471
|
+
body = `<iframe class="stage" allow="clipboard-read; clipboard-write" src="${esc(info.liveViewUrl)}"></iframe>
|
|
17472
|
+
<div class="footer">
|
|
17473
|
+
<span class="muted">Log into ${domainLabel} directly in the window above, then confirm below.</span>
|
|
17474
|
+
<span class="spacer"></span>
|
|
17475
|
+
<button class="btn" id="done">Done \u2014 I'm signed in</button>
|
|
17476
|
+
</div>`;
|
|
17477
|
+
} else {
|
|
17478
|
+
body = `<div class="empty">
|
|
16923
17479
|
<div>This sign-in link is no longer active.</div>
|
|
16924
17480
|
<div class="muted">Ask the assistant to reconnect the profile, then open the new link.</div>
|
|
16925
17481
|
</div>`;
|
|
17482
|
+
}
|
|
16926
17483
|
return `<!DOCTYPE html>
|
|
16927
17484
|
<html lang="en">
|
|
16928
17485
|
<head>
|
|
@@ -16938,9 +17495,11 @@ function renderAuthConsoleHtml(connectionId, hostedUrl) {
|
|
|
16938
17495
|
header .muted { color: #6b7689; font-size: 12px; }
|
|
16939
17496
|
.spacer { flex: 1; }
|
|
16940
17497
|
.stage { flex: 1; width: 100%; border: 0; display: block; background: #05070b; }
|
|
16941
|
-
.
|
|
16942
|
-
.btn { background: #2b6cff; color: #fff; border-radius: 7px; padding:
|
|
17498
|
+
.footer { display: flex; align-items: center; gap: 12px; padding: 10px 18px; border-top: 1px solid #1c2230; background: #0f131c; font-size: 13px; color: #8893a7; }
|
|
17499
|
+
.btn { background: #2b6cff; color: #fff; border: 0; border-radius: 7px; padding: 8px 14px; text-decoration: none; font-weight: 500; font: inherit; cursor: pointer; }
|
|
17500
|
+
.btn:disabled { opacity: .6; cursor: default; }
|
|
16943
17501
|
.empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: #8893a7; }
|
|
17502
|
+
.check { font-size: 32px; color: #36d399; }
|
|
16944
17503
|
.muted { color: #6b7689; font-size: 12px; }
|
|
16945
17504
|
</style>
|
|
16946
17505
|
${ATTRIBUTION_PIXEL_SCRIPT}
|
|
@@ -16950,9 +17509,23 @@ ${ATTRIBUTION_PIXEL_SCRIPT}
|
|
|
16950
17509
|
<h1>MCP Scraper</h1>
|
|
16951
17510
|
<span class="muted">Secure sign-in \xB7 ${safeId}</span>
|
|
16952
17511
|
<span class="spacer"></span>
|
|
16953
|
-
<span class="muted">
|
|
17512
|
+
<span class="muted">Log in directly to the real site above \u2014 your session is saved to your profile.</span>
|
|
16954
17513
|
</header>
|
|
16955
17514
|
${body}
|
|
17515
|
+
<script>
|
|
17516
|
+
(function(){
|
|
17517
|
+
var doneBtn = document.getElementById('done');
|
|
17518
|
+
if (!doneBtn) return;
|
|
17519
|
+
doneBtn.onclick = function() {
|
|
17520
|
+
doneBtn.disabled = true;
|
|
17521
|
+
doneBtn.textContent = 'Saving\u2026';
|
|
17522
|
+
fetch('/console/auth/${encodeURIComponent(connectionId)}/complete', { method: 'POST' })
|
|
17523
|
+
.then(function(r){ return r.json().catch(function(){ return {}; }); })
|
|
17524
|
+
.then(function(){ location.reload(); })
|
|
17525
|
+
.catch(function(){ doneBtn.disabled = false; doneBtn.textContent = "Done \u2014 I'm signed in"; });
|
|
17526
|
+
};
|
|
17527
|
+
})();
|
|
17528
|
+
</script>
|
|
16956
17529
|
</body>
|
|
16957
17530
|
</html>`;
|
|
16958
17531
|
}
|
|
@@ -17190,8 +17763,9 @@ stripeApp.post("/webhooks", async (c) => {
|
|
|
17190
17763
|
const user2 = await resolveUser(sub.customer, sub.customer_email);
|
|
17191
17764
|
if (user2) {
|
|
17192
17765
|
const live = sub.status === "active" || sub.status === "trialing";
|
|
17193
|
-
|
|
17194
|
-
await
|
|
17766
|
+
const newMemoryPlan = live ? mem.plan : "free";
|
|
17767
|
+
await setMemoryPlan(user2.id, newMemoryPlan, live ? sub.id : null);
|
|
17768
|
+
await syncMemoryKeyPlan(user2, resolveEffectiveMemoryPlan({ ...user2, memory_plan: newMemoryPlan }));
|
|
17195
17769
|
}
|
|
17196
17770
|
return c.json({ received: true });
|
|
17197
17771
|
}
|
|
@@ -17209,7 +17783,9 @@ stripeApp.post("/webhooks", async (c) => {
|
|
|
17209
17783
|
if (priceId && priceId in SUBSCRIPTION_TIERS) {
|
|
17210
17784
|
const tier = SUBSCRIPTION_TIERS[priceId];
|
|
17211
17785
|
const live = sub.status === "active" || sub.status === "trialing";
|
|
17212
|
-
|
|
17786
|
+
const newTier = live ? tier.tier : null;
|
|
17787
|
+
await setSubscriptionTier(user.id, newTier, live ? tier.concurrency : 0, live ? sub.id : null);
|
|
17788
|
+
await syncMemoryKeyPlan(user, resolveEffectiveMemoryPlan({ ...user, subscription_tier: newTier }));
|
|
17213
17789
|
} else if (priceId === CONCURRENCY_PRICE_ID && event.type === "customer.subscription.created") {
|
|
17214
17790
|
await setExtraConcurrencySlots(user.id, user.extra_concurrency_slots + 1);
|
|
17215
17791
|
await setConcurrencySubId(user.id, sub.id);
|
|
@@ -17222,7 +17798,7 @@ stripeApp.post("/webhooks", async (c) => {
|
|
|
17222
17798
|
const user2 = await resolveUserByMemorySubscription(sub.id) ?? await getUserByStripeCustomerId(sub.customer);
|
|
17223
17799
|
if (user2) {
|
|
17224
17800
|
await setMemoryPlan(user2.id, "free", null);
|
|
17225
|
-
await syncMemoryKeyPlan(user2, "free");
|
|
17801
|
+
await syncMemoryKeyPlan(user2, resolveEffectiveMemoryPlan({ ...user2, memory_plan: "free" }));
|
|
17226
17802
|
}
|
|
17227
17803
|
return c.json({ received: true });
|
|
17228
17804
|
}
|
|
@@ -17235,6 +17811,7 @@ stripeApp.post("/webhooks", async (c) => {
|
|
|
17235
17811
|
if (!user) return c.json({ received: true });
|
|
17236
17812
|
if (priceId && priceId in SUBSCRIPTION_TIERS) {
|
|
17237
17813
|
await setSubscriptionTier(user.id, null, 0, null);
|
|
17814
|
+
await syncMemoryKeyPlan(user, resolveEffectiveMemoryPlan({ ...user, subscription_tier: null }));
|
|
17238
17815
|
} else if (priceId === CONCURRENCY_PRICE_ID) {
|
|
17239
17816
|
await setExtraConcurrencySlots(user.id, Math.max(0, user.extra_concurrency_slots - 1));
|
|
17240
17817
|
await setConcurrencySubId(user.id, null);
|
|
@@ -20467,7 +21044,7 @@ app.get("/cron/tick", async (c) => {
|
|
|
20467
21044
|
if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
|
|
20468
21045
|
return c.json({ error: "Unauthorized" }, 401);
|
|
20469
21046
|
}
|
|
20470
|
-
const { drainQueue } = await import("./worker-
|
|
21047
|
+
const { drainQueue } = await import("./worker-7XRZNLKB.js");
|
|
20471
21048
|
const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
|
|
20472
21049
|
const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
|
|
20473
21050
|
const [results, sweepResult, reapResult, expiredResult, blobCleanup] = await Promise.all([
|
|
@@ -20485,7 +21062,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
20485
21062
|
return c.json({ error: "Unauthorized" }, 401);
|
|
20486
21063
|
}
|
|
20487
21064
|
const jobId = c.req.param("id");
|
|
20488
|
-
const { getExtractJob: getExtractJob2, completeExtractJob: completeExtractJob2 } = await import("./site-extract-repository-
|
|
21065
|
+
const { getExtractJob: getExtractJob2, completeExtractJob: completeExtractJob2 } = await import("./site-extract-repository-4NVO5KQA.js");
|
|
20489
21066
|
const { assembleExtractArtifacts } = await import("./extract-bundle-UKE273TV.js");
|
|
20490
21067
|
const job = await getExtractJob2(jobId);
|
|
20491
21068
|
if (!job) return c.json({ error: "job not found" }, 404);
|
|
@@ -20493,7 +21070,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
20493
21070
|
await completeExtractJob2(jobId, stored);
|
|
20494
21071
|
let settlement = "already_settled_or_refunded";
|
|
20495
21072
|
if (job.billedMc == null && job.userId != null) {
|
|
20496
|
-
const { settleExtractJob: settleExtractJob2, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-
|
|
21073
|
+
const { settleExtractJob: settleExtractJob2, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-4NVO5KQA.js");
|
|
20497
21074
|
const heldMc = Number(job.options.heldMc ?? 0);
|
|
20498
21075
|
const successful = await countSuccessfulPages2(jobId);
|
|
20499
21076
|
const usedMc = Math.min(successful * MC_COSTS.page_scrape, heldMc);
|
|
@@ -20531,14 +21108,20 @@ app.get("/console/auth/:id", async (c) => {
|
|
|
20531
21108
|
const id = c.req.param("id");
|
|
20532
21109
|
await migrateBrowserAgent();
|
|
20533
21110
|
const row = await getAuthConnectionRow(id);
|
|
20534
|
-
|
|
21111
|
+
const sessionRow = row?.browser_agent_session_id ? await getSessionRow(row.browser_agent_session_id) : null;
|
|
21112
|
+
return c.html(renderAuthConsoleHtml(id, {
|
|
21113
|
+
domain: row?.domain ?? null,
|
|
21114
|
+
status: row?.status ?? null,
|
|
21115
|
+
liveViewUrl: sessionRow?.live_view_url ?? null,
|
|
21116
|
+
sessionOpen: sessionRow?.status === "open"
|
|
21117
|
+
}));
|
|
20535
21118
|
});
|
|
20536
|
-
app.
|
|
21119
|
+
app.post("/console/auth/:id/complete", async (c) => {
|
|
20537
21120
|
const id = c.req.param("id");
|
|
20538
21121
|
await migrateBrowserAgent();
|
|
20539
|
-
const
|
|
20540
|
-
if (!
|
|
20541
|
-
return c.
|
|
21122
|
+
const result = await completeAuthConnection(id);
|
|
21123
|
+
if (!result.ok) return c.json({ error: result.error }, 404);
|
|
21124
|
+
return c.json({ ok: true });
|
|
20542
21125
|
});
|
|
20543
21126
|
app.get("/console/:id", (c) => c.html(renderConsoleHtml(c.req.param("id"))));
|
|
20544
21127
|
app.route("/stripe", stripeApp);
|
|
@@ -20649,4 +21232,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
20649
21232
|
export {
|
|
20650
21233
|
app
|
|
20651
21234
|
};
|
|
20652
|
-
//# sourceMappingURL=server-
|
|
21235
|
+
//# sourceMappingURL=server-6IYQQK6X.js.map
|