mcp-scraper 0.3.18 → 0.3.19
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 +61 -12
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- 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 +1 -1
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/{chunk-2XCNU22L.js → chunk-A46NKAAM.js} +2 -2
- package/dist/chunk-AUKOY2IV.js +7 -0
- package/dist/chunk-AUKOY2IV.js.map +1 -0
- package/dist/{chunk-HDPWLYK7.js → chunk-T337IGVE.js} +3 -3
- package/dist/chunk-T337IGVE.js.map +1 -0
- package/dist/{server-3M3XCVOT.js → server-EYNMXWUJ.js} +61 -14
- package/dist/server-EYNMXWUJ.js.map +1 -0
- package/dist/{worker-J6I5XP2F.js → worker-YZ2ZJE4F.js} +2 -2
- package/docs/mcp-tool-manifest.generated.json +1 -1
- package/package.json +1 -1
- package/dist/chunk-C7ZNIXOA.js +0 -7
- package/dist/chunk-C7ZNIXOA.js.map +0 -1
- package/dist/chunk-HDPWLYK7.js.map +0 -1
- package/dist/server-3M3XCVOT.js.map +0 -1
- /package/dist/{chunk-2XCNU22L.js.map → chunk-A46NKAAM.js.map} +0 -0
- /package/dist/{worker-J6I5XP2F.js.map → worker-YZ2ZJE4F.js.map} +0 -0
package/dist/bin/api-server.cjs
CHANGED
|
@@ -9661,8 +9661,8 @@ var init_rates = __esm({
|
|
|
9661
9661
|
label: "Interactive browser session",
|
|
9662
9662
|
aliases: ["browser_open", "browser agent", "browser_agent", "live browser", "browse", "browser control", "interactive browser"],
|
|
9663
9663
|
credits: mcToCredits(MC_COSTS.browser_minute),
|
|
9664
|
-
unit: "per minute
|
|
9665
|
-
notes: "Metered
|
|
9664
|
+
unit: "per minute the browser is open",
|
|
9665
|
+
notes: "Metered for the full time the browser session is open (active or idle) \u2014 every minute the session stays alive is billed. Close the session to stop the meter; abandoned sessions are auto-closed after a short idle window."
|
|
9666
9666
|
}
|
|
9667
9667
|
];
|
|
9668
9668
|
CONCURRENCY_PRICE_ID = "price_1Ta1NRS8aAcsk3TGwsRnYbix";
|
|
@@ -12478,6 +12478,8 @@ var init_screenshot_routes = __esm({
|
|
|
12478
12478
|
init_api_auth();
|
|
12479
12479
|
init_url_utils();
|
|
12480
12480
|
init_concurrency_gates();
|
|
12481
|
+
init_db();
|
|
12482
|
+
init_rates();
|
|
12481
12483
|
ScreenshotBodySchema = import_zod14.z.object({
|
|
12482
12484
|
url: import_zod14.z.string().trim().min(1, "url is required"),
|
|
12483
12485
|
device: import_zod14.z.string().trim().optional(),
|
|
@@ -12516,7 +12518,11 @@ var init_screenshot_routes = __esm({
|
|
|
12516
12518
|
metadata: { url: targetUrl, device }
|
|
12517
12519
|
});
|
|
12518
12520
|
if (!gate.ok) return c.json(concurrencyLimitExceededResponse(gate), 429, { "Retry-After": String(gate.retryAfterSeconds) });
|
|
12521
|
+
let debited = false;
|
|
12519
12522
|
try {
|
|
12523
|
+
const { ok, balance_mc } = await debitMc(user.id, MC_COSTS.page_scrape, LedgerOperation.EXTRACT_URL, targetUrl);
|
|
12524
|
+
if (!ok) return c.json(insufficientBalanceResponse(balance_mc, MC_COSTS.page_scrape), 402);
|
|
12525
|
+
debited = true;
|
|
12520
12526
|
const buf = await captureScreenshot(targetUrl, browserServiceApiKey(), device);
|
|
12521
12527
|
return new Response(new Uint8Array(buf), {
|
|
12522
12528
|
status: 200,
|
|
@@ -12527,6 +12533,7 @@ var init_screenshot_routes = __esm({
|
|
|
12527
12533
|
}
|
|
12528
12534
|
});
|
|
12529
12535
|
} catch (err) {
|
|
12536
|
+
if (debited) await creditMc(user.id, MC_COSTS.page_scrape, LedgerOperation.EXTRACT_URL, "failed screenshot refund");
|
|
12530
12537
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12531
12538
|
return c.json({ error: msg }, 502);
|
|
12532
12539
|
} finally {
|
|
@@ -23755,7 +23762,7 @@ var PACKAGE_VERSION;
|
|
|
23755
23762
|
var init_version = __esm({
|
|
23756
23763
|
"src/version.ts"() {
|
|
23757
23764
|
"use strict";
|
|
23758
|
-
PACKAGE_VERSION = "0.3.
|
|
23765
|
+
PACKAGE_VERSION = "0.3.19";
|
|
23759
23766
|
}
|
|
23760
23767
|
});
|
|
23761
23768
|
|
|
@@ -25670,6 +25677,14 @@ async function listSessionRows(userId, includeClosed = false) {
|
|
|
25670
25677
|
});
|
|
25671
25678
|
return res.rows;
|
|
25672
25679
|
}
|
|
25680
|
+
async function listIdleOpenSessionRows(idleSeconds) {
|
|
25681
|
+
const db = getDb();
|
|
25682
|
+
const res = await db.execute({
|
|
25683
|
+
sql: `SELECT * FROM browser_agent_sessions WHERE status = 'open' AND COALESCE(last_action_at, created_at) <= datetime('now', ?) ORDER BY created_at LIMIT 200`,
|
|
25684
|
+
args: [`-${Math.max(1, Math.round(idleSeconds))} seconds`]
|
|
25685
|
+
});
|
|
25686
|
+
return res.rows;
|
|
25687
|
+
}
|
|
25673
25688
|
async function addActiveMs(id, deltaMs) {
|
|
25674
25689
|
const db = getDb();
|
|
25675
25690
|
await db.execute({
|
|
@@ -27062,16 +27077,42 @@ function browserSessionLockTtlSeconds(timeoutSeconds) {
|
|
|
27062
27077
|
}
|
|
27063
27078
|
return DEFAULT_BROWSER_SESSION_LOCK_TTL_SECONDS;
|
|
27064
27079
|
}
|
|
27065
|
-
async function charge(sessionId, userId,
|
|
27066
|
-
const
|
|
27067
|
-
|
|
27068
|
-
const
|
|
27069
|
-
|
|
27080
|
+
async function charge(sessionId, userId, _startedAtMs) {
|
|
27081
|
+
const row = await getSessionRow(sessionId);
|
|
27082
|
+
if (!row) return;
|
|
27083
|
+
const createdMs = parseAgentDate(row.created_at);
|
|
27084
|
+
if (createdMs == null) return;
|
|
27085
|
+
const uptimeMs = Math.max(0, Date.now() - createdMs);
|
|
27086
|
+
const owed = browserActiveCostMc(uptimeMs);
|
|
27087
|
+
await addActiveMs(sessionId, 0);
|
|
27088
|
+
const delta = owed - Number(row.billed_mc ?? 0);
|
|
27070
27089
|
if (delta > 0) {
|
|
27071
27090
|
const res = await debitMc(userId, delta, LedgerOperation.BROWSER_SESSION, sessionId);
|
|
27072
27091
|
if (res.ok) await setBilledMc(sessionId, owed);
|
|
27073
27092
|
}
|
|
27074
27093
|
}
|
|
27094
|
+
async function reapIdleBrowserSessions(idleSeconds = 120) {
|
|
27095
|
+
const rows = await listIdleOpenSessionRows(idleSeconds);
|
|
27096
|
+
let reaped = 0;
|
|
27097
|
+
for (const row of rows) {
|
|
27098
|
+
if (row.user_id != null) {
|
|
27099
|
+
try {
|
|
27100
|
+
await charge(row.id, row.user_id);
|
|
27101
|
+
} catch {
|
|
27102
|
+
}
|
|
27103
|
+
}
|
|
27104
|
+
try {
|
|
27105
|
+
await closeSession(row.runtime_session_id);
|
|
27106
|
+
} catch {
|
|
27107
|
+
}
|
|
27108
|
+
await markSessionClosed(row.id).catch(() => {
|
|
27109
|
+
});
|
|
27110
|
+
if (row.concurrency_lock_id) await releaseConcurrencyGate(row.concurrency_lock_id).catch(() => {
|
|
27111
|
+
});
|
|
27112
|
+
reaped++;
|
|
27113
|
+
}
|
|
27114
|
+
return { reaped };
|
|
27115
|
+
}
|
|
27075
27116
|
function publicSession(row) {
|
|
27076
27117
|
return {
|
|
27077
27118
|
session_id: row.id,
|
|
@@ -27081,10 +27122,16 @@ function publicSession(row) {
|
|
|
27081
27122
|
created_at: row.created_at,
|
|
27082
27123
|
last_action_at: row.last_action_at,
|
|
27083
27124
|
closed_at: row.closed_at,
|
|
27084
|
-
|
|
27125
|
+
uptime_seconds: uptimeSeconds(row),
|
|
27085
27126
|
credits_used: Math.round((row.billed_mc ?? 0) / 10) / 100
|
|
27086
27127
|
};
|
|
27087
27128
|
}
|
|
27129
|
+
function uptimeSeconds(row) {
|
|
27130
|
+
const createdMs = parseAgentDate(row.created_at);
|
|
27131
|
+
const endMs = row.closed_at ? parseAgentDate(row.closed_at) : Date.now();
|
|
27132
|
+
if (createdMs == null || endMs == null) return 0;
|
|
27133
|
+
return Math.max(0, Math.round((endMs - createdMs) / 1e3));
|
|
27134
|
+
}
|
|
27088
27135
|
function failure(err) {
|
|
27089
27136
|
const msg = err instanceof Error ? err.message : String(err);
|
|
27090
27137
|
return { error: sanitizeVendorName(msg) };
|
|
@@ -27296,6 +27343,7 @@ function buildBrowserAgentRoutes() {
|
|
|
27296
27343
|
const user = c.get("user");
|
|
27297
27344
|
const row = await loadOpenSession(c.req.param("id"), user.id);
|
|
27298
27345
|
if (!row) return c.json({ error: "not found" }, 404);
|
|
27346
|
+
await charge(row.id, user.id);
|
|
27299
27347
|
try {
|
|
27300
27348
|
await closeSession(row.runtime_session_id);
|
|
27301
27349
|
} catch {
|
|
@@ -29240,11 +29288,12 @@ var init_server = __esm({
|
|
|
29240
29288
|
const { drainQueue: drainQueue2 } = await Promise.resolve().then(() => (init_worker(), worker_exports));
|
|
29241
29289
|
const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
|
|
29242
29290
|
const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
|
|
29243
|
-
const [results, sweepResult] = await Promise.all([
|
|
29291
|
+
const [results, sweepResult, reapResult] = await Promise.all([
|
|
29244
29292
|
drainQueue2(budget),
|
|
29245
|
-
runMonthlyRefreshSweep()
|
|
29293
|
+
runMonthlyRefreshSweep(),
|
|
29294
|
+
reapIdleBrowserSessions(120).catch(() => ({ reaped: 0 }))
|
|
29246
29295
|
]);
|
|
29247
|
-
return c.json({ drained: results.length, results, sweepResult, workflowDispatch: workflowDispatchResult });
|
|
29296
|
+
return c.json({ drained: results.length, results, sweepResult, reaped: reapResult, workflowDispatch: workflowDispatchResult });
|
|
29248
29297
|
});
|
|
29249
29298
|
app.on(["GET", "POST", "PUT"], "/api/inngest", (0, import_hono14.serve)({ client: inngest, functions: [siteAuditFn, siteExtractFn] }));
|
|
29250
29299
|
app.route("/api/internal/site-architecture-auditor", siteAuditApp);
|