mcp-scraper 0.3.46 → 0.4.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/dist/bin/api-server.cjs +2800 -346
- 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 +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 +2100 -23
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +9 -4
- package/dist/bin/mcp-stdio-server.js.map +1 -1
- package/dist/bin/paa-harvest.js +3 -2
- package/dist/bin/paa-harvest.js.map +1 -1
- package/dist/{chunk-SS5YBZVI.js → chunk-3NIPPJGP.js} +2184 -514
- package/dist/chunk-3NIPPJGP.js.map +1 -0
- package/dist/chunk-3UH3BEIZ.js +158 -0
- package/dist/chunk-3UH3BEIZ.js.map +1 -0
- package/dist/{chunk-BRVX6RDN.js → chunk-6TDUY7CA.js} +5 -159
- package/dist/chunk-6TDUY7CA.js.map +1 -0
- package/dist/chunk-GWRIO6JT.js +419 -0
- package/dist/chunk-GWRIO6JT.js.map +1 -0
- package/dist/{chunk-RXNHY3TF.js → chunk-HBC4C75S.js} +11 -9
- package/dist/{chunk-RXNHY3TF.js.map → chunk-HBC4C75S.js.map} +1 -1
- package/dist/chunk-HPV4VOQX.js +27 -0
- package/dist/chunk-HPV4VOQX.js.map +1 -0
- package/dist/chunk-IXDYL7TE.js +7 -0
- package/dist/chunk-IXDYL7TE.js.map +1 -0
- package/dist/chunk-JOEZJL4I.js +130 -0
- package/dist/chunk-JOEZJL4I.js.map +1 -0
- package/dist/{chunk-3PRO376E.js → chunk-M2S27J6Z.js} +1 -25
- package/dist/chunk-M2S27J6Z.js.map +1 -0
- package/dist/extract-bundle-UKE273TV.js +276 -0
- package/dist/extract-bundle-UKE273TV.js.map +1 -0
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/{server-MGE3GYJW.js → server-Z4WKTE6F.js} +169 -195
- package/dist/server-Z4WKTE6F.js.map +1 -0
- package/dist/site-extract-repository-2MQBAOX5.js +30 -0
- package/dist/site-extract-repository-2MQBAOX5.js.map +1 -0
- package/dist/{worker-4CVMSUZR.js → worker-RVZXIALX.js} +8 -5
- package/dist/{worker-4CVMSUZR.js.map → worker-RVZXIALX.js.map} +1 -1
- package/package.json +2 -1
- package/dist/chunk-3PRO376E.js.map +0 -1
- package/dist/chunk-BRVX6RDN.js.map +0 -1
- package/dist/chunk-SS5YBZVI.js.map +0 -1
- package/dist/chunk-WT6OT2T3.js +0 -7
- package/dist/chunk-WT6OT2T3.js.map +0 -1
- package/dist/server-MGE3GYJW.js.map +0 -1
|
@@ -1,24 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
classifyHarvestProblem,
|
|
3
|
+
createHarvestAttemptRecorder,
|
|
4
|
+
harvestProblemResponse,
|
|
5
|
+
serializeHarvestProblem
|
|
6
|
+
} from "./chunk-3UH3BEIZ.js";
|
|
7
|
+
import {
|
|
8
|
+
BrowserDriver,
|
|
9
|
+
MapsSelectors,
|
|
10
|
+
buildYouTubeChannelVideosUrl,
|
|
11
|
+
currentCostContext,
|
|
12
|
+
deleteKernelProxyId,
|
|
13
|
+
harvest,
|
|
14
|
+
migrateCostTelemetry,
|
|
15
|
+
recordKernelSession,
|
|
16
|
+
recordVendorUsage,
|
|
17
|
+
resolveKernelProxyId,
|
|
18
|
+
runWithCostContext
|
|
19
|
+
} from "./chunk-HBC4C75S.js";
|
|
1
20
|
import {
|
|
2
21
|
HttpMcpToolExecutor,
|
|
3
|
-
|
|
4
|
-
buildLinkGraph,
|
|
5
|
-
buildLinkReport,
|
|
22
|
+
MemoryMcpToolExecutor,
|
|
6
23
|
buildPaaExtractorMcpServer,
|
|
7
|
-
computeIssues,
|
|
8
24
|
configureReportSaving,
|
|
9
25
|
exportFanout,
|
|
10
|
-
getBlobStore,
|
|
11
26
|
harvestTimeoutBudget,
|
|
12
27
|
hashOwnerId,
|
|
13
28
|
outputBaseDir,
|
|
14
29
|
registerBrowserAgentMcpTools,
|
|
30
|
+
registerMemoryMcpTools,
|
|
15
31
|
registerSerpIntelligenceCaptureTools,
|
|
16
|
-
renderImageSection,
|
|
17
|
-
renderIssueReport,
|
|
18
|
-
renderLinkReport,
|
|
19
32
|
sanitizeAttempts,
|
|
20
33
|
sanitizeHarvestResult
|
|
21
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-3NIPPJGP.js";
|
|
35
|
+
import {
|
|
36
|
+
auditImages,
|
|
37
|
+
getBlobStore
|
|
38
|
+
} from "./chunk-GWRIO6JT.js";
|
|
39
|
+
import {
|
|
40
|
+
browserServiceApiKey,
|
|
41
|
+
browserServiceProfileName,
|
|
42
|
+
browserServiceProfileSaveChanges,
|
|
43
|
+
browserServiceProxyId
|
|
44
|
+
} from "./chunk-HPV4VOQX.js";
|
|
22
45
|
import {
|
|
23
46
|
csvRecords,
|
|
24
47
|
listWorkflowDefinitions,
|
|
@@ -31,7 +54,29 @@ import {
|
|
|
31
54
|
workflowStepCount,
|
|
32
55
|
workflowSupportsSteps
|
|
33
56
|
} from "./chunk-NNEIXK5L.js";
|
|
34
|
-
import "./chunk-
|
|
57
|
+
import "./chunk-K443GQY5.js";
|
|
58
|
+
import {
|
|
59
|
+
DEFAULT_MAPS_PROXY_MODE,
|
|
60
|
+
DEFAULT_PROXY_MODE,
|
|
61
|
+
MapsPlaceOptionsSchema,
|
|
62
|
+
MapsSearchOptionsSchema,
|
|
63
|
+
RawMapsAboutAttributeSchema,
|
|
64
|
+
RawMapsHoursRowSchema,
|
|
65
|
+
RawMapsOverviewSchema,
|
|
66
|
+
RawMapsReviewStatsSchema
|
|
67
|
+
} from "./chunk-BP27CZ5Q.js";
|
|
68
|
+
import "./chunk-IXDYL7TE.js";
|
|
69
|
+
import {
|
|
70
|
+
completeExtractJob,
|
|
71
|
+
countSuccessfulPages,
|
|
72
|
+
createExtractJob,
|
|
73
|
+
failExtractJob,
|
|
74
|
+
getExtractJob,
|
|
75
|
+
getExtractedPages,
|
|
76
|
+
saveExtractPages,
|
|
77
|
+
setExtractJobTotal,
|
|
78
|
+
settleExtractJob
|
|
79
|
+
} from "./chunk-JOEZJL4I.js";
|
|
35
80
|
import {
|
|
36
81
|
BROWSER_OPEN_MIN_BALANCE_MC,
|
|
37
82
|
CONCURRENCY_PRICE_ID,
|
|
@@ -48,46 +93,14 @@ import {
|
|
|
48
93
|
SUBSCRIPTION_TIERS,
|
|
49
94
|
SUBSCRIPTION_TIER_BY_KEY,
|
|
50
95
|
browserActiveCostMc,
|
|
51
|
-
classifyHarvestProblem,
|
|
52
96
|
concurrencySlotBillingInfo,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
insufficientBalanceResponse,
|
|
56
|
-
serializeHarvestProblem
|
|
57
|
-
} from "./chunk-BRVX6RDN.js";
|
|
58
|
-
import {
|
|
59
|
-
BrowserDriver,
|
|
60
|
-
MapsSelectors,
|
|
61
|
-
buildYouTubeChannelVideosUrl,
|
|
62
|
-
currentCostContext,
|
|
63
|
-
deleteKernelProxyId,
|
|
64
|
-
harvest,
|
|
65
|
-
migrateCostTelemetry,
|
|
66
|
-
recordKernelSession,
|
|
67
|
-
recordVendorUsage,
|
|
68
|
-
resolveKernelProxyId,
|
|
69
|
-
runWithCostContext
|
|
70
|
-
} from "./chunk-RXNHY3TF.js";
|
|
97
|
+
insufficientBalanceResponse
|
|
98
|
+
} from "./chunk-6TDUY7CA.js";
|
|
71
99
|
import {
|
|
72
100
|
CaptchaError,
|
|
73
101
|
RECAPTCHA_INSTRUCTIONS,
|
|
74
|
-
browserServiceApiKey,
|
|
75
|
-
browserServiceProfileName,
|
|
76
|
-
browserServiceProfileSaveChanges,
|
|
77
|
-
browserServiceProxyId,
|
|
78
102
|
sanitizeVendorName
|
|
79
|
-
} from "./chunk-
|
|
80
|
-
import "./chunk-K443GQY5.js";
|
|
81
|
-
import {
|
|
82
|
-
DEFAULT_MAPS_PROXY_MODE,
|
|
83
|
-
DEFAULT_PROXY_MODE,
|
|
84
|
-
MapsPlaceOptionsSchema,
|
|
85
|
-
MapsSearchOptionsSchema,
|
|
86
|
-
RawMapsAboutAttributeSchema,
|
|
87
|
-
RawMapsHoursRowSchema,
|
|
88
|
-
RawMapsOverviewSchema,
|
|
89
|
-
RawMapsReviewStatsSchema
|
|
90
|
-
} from "./chunk-BP27CZ5Q.js";
|
|
103
|
+
} from "./chunk-M2S27J6Z.js";
|
|
91
104
|
import {
|
|
92
105
|
SiteAuditJobRowSchema,
|
|
93
106
|
advanceWorkflowRunStep,
|
|
@@ -7422,135 +7435,8 @@ var siteAuditFn = inngest.createFunction(
|
|
|
7422
7435
|
}
|
|
7423
7436
|
);
|
|
7424
7437
|
|
|
7425
|
-
// src/api/site-extract-repository.ts
|
|
7426
|
-
function rowToJob(r) {
|
|
7427
|
-
return {
|
|
7428
|
-
id: String(r.id),
|
|
7429
|
-
userId: r.user_id != null ? Number(r.user_id) : null,
|
|
7430
|
-
status: r.status != null ? String(r.status) : "pending",
|
|
7431
|
-
startUrl: String(r.start_url ?? ""),
|
|
7432
|
-
options: r.options ? JSON.parse(String(r.options)) : {},
|
|
7433
|
-
totalUrls: Number(r.total_urls ?? 0),
|
|
7434
|
-
doneUrls: Number(r.done_urls ?? 0),
|
|
7435
|
-
artifacts: r.artifacts ? JSON.parse(String(r.artifacts)) : null,
|
|
7436
|
-
error: r.error != null ? String(r.error) : null,
|
|
7437
|
-
billedMc: r.billed_mc != null ? Number(r.billed_mc) : null,
|
|
7438
|
-
createdAt: String(r.created_at ?? ""),
|
|
7439
|
-
updatedAt: String(r.updated_at ?? "")
|
|
7440
|
-
};
|
|
7441
|
-
}
|
|
7442
|
-
async function createExtractJob(jobId, userId, startUrl, options) {
|
|
7443
|
-
const db = getDb();
|
|
7444
|
-
await db.execute({
|
|
7445
|
-
sql: `INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)
|
|
7446
|
-
VALUES (?, ?, 'pending', ?, ?, datetime('now'), datetime('now'))`,
|
|
7447
|
-
args: [jobId, userId, startUrl, JSON.stringify(options)]
|
|
7448
|
-
});
|
|
7449
|
-
}
|
|
7450
|
-
async function getExtractJob(jobId) {
|
|
7451
|
-
const db = getDb();
|
|
7452
|
-
const res = await db.execute({ sql: `SELECT * FROM site_extract_jobs WHERE id = ?`, args: [jobId] });
|
|
7453
|
-
return res.rows[0] ? rowToJob(res.rows[0]) : null;
|
|
7454
|
-
}
|
|
7455
|
-
async function setExtractJobTotal(jobId, totalUrls) {
|
|
7456
|
-
const db = getDb();
|
|
7457
|
-
await db.execute({
|
|
7458
|
-
sql: `UPDATE site_extract_jobs SET status = 'running', total_urls = ?, updated_at = datetime('now') WHERE id = ?`,
|
|
7459
|
-
args: [totalUrls, jobId]
|
|
7460
|
-
});
|
|
7461
|
-
}
|
|
7462
|
-
async function saveExtractPages(jobId, pages) {
|
|
7463
|
-
if (pages.length === 0) return;
|
|
7464
|
-
const db = getDb();
|
|
7465
|
-
await db.batch(
|
|
7466
|
-
pages.map((p) => ({
|
|
7467
|
-
sql: `INSERT OR REPLACE INTO site_extract_pages (job_id, url, page) VALUES (?, ?, ?)`,
|
|
7468
|
-
args: [jobId, p.url, JSON.stringify({ ...p, bodyMarkdown: "", schema: [] })]
|
|
7469
|
-
}))
|
|
7470
|
-
);
|
|
7471
|
-
await db.execute({
|
|
7472
|
-
sql: `UPDATE site_extract_jobs
|
|
7473
|
-
SET done_urls = (SELECT COUNT(*) FROM site_extract_pages WHERE job_id = ?), updated_at = datetime('now')
|
|
7474
|
-
WHERE id = ?`,
|
|
7475
|
-
args: [jobId, jobId]
|
|
7476
|
-
});
|
|
7477
|
-
}
|
|
7478
|
-
async function getExtractedPages(jobId) {
|
|
7479
|
-
const db = getDb();
|
|
7480
|
-
const res = await db.execute({ sql: `SELECT page FROM site_extract_pages WHERE job_id = ?`, args: [jobId] });
|
|
7481
|
-
return res.rows.map((r) => JSON.parse(String(r.page)));
|
|
7482
|
-
}
|
|
7483
|
-
async function countSuccessfulPages(jobId) {
|
|
7484
|
-
const db = getDb();
|
|
7485
|
-
const res = await db.execute({
|
|
7486
|
-
sql: `SELECT COUNT(*) AS n FROM site_extract_pages
|
|
7487
|
-
WHERE job_id = ? AND json_extract(page, '$.status') = 200 AND json_extract(page, '$.wordCount') > 0`,
|
|
7488
|
-
args: [jobId]
|
|
7489
|
-
});
|
|
7490
|
-
return Number(res.rows[0]?.n ?? 0);
|
|
7491
|
-
}
|
|
7492
|
-
async function completeExtractJob(jobId, artifacts) {
|
|
7493
|
-
const db = getDb();
|
|
7494
|
-
await db.execute({
|
|
7495
|
-
sql: `UPDATE site_extract_jobs SET status = 'complete', artifacts = ?, updated_at = datetime('now') WHERE id = ?`,
|
|
7496
|
-
args: [JSON.stringify(artifacts ?? []), jobId]
|
|
7497
|
-
});
|
|
7498
|
-
}
|
|
7499
|
-
async function failExtractJob(jobId, error) {
|
|
7500
|
-
const db = getDb();
|
|
7501
|
-
await db.execute({
|
|
7502
|
-
sql: `UPDATE site_extract_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?`,
|
|
7503
|
-
args: [sanitizeVendorName(error).slice(0, 2e3), jobId]
|
|
7504
|
-
});
|
|
7505
|
-
}
|
|
7506
|
-
async function settleExtractJob(jobId, userId, refundMc, netChargeMc, reference) {
|
|
7507
|
-
const db = getDb();
|
|
7508
|
-
const job = await getExtractJob(jobId);
|
|
7509
|
-
if (!job || job.billedMc != null) return;
|
|
7510
|
-
if (refundMc <= 0) {
|
|
7511
|
-
await db.execute({ sql: `UPDATE site_extract_jobs SET billed_mc = ?, updated_at = datetime('now') WHERE id = ? AND billed_mc IS NULL`, args: [Math.max(0, netChargeMc), jobId] });
|
|
7512
|
-
return;
|
|
7513
|
-
}
|
|
7514
|
-
await db.batch([
|
|
7515
|
-
{ sql: "UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?", args: [refundMc, userId] },
|
|
7516
|
-
{ sql: "INSERT INTO ledger (user_id, amount_mc, operation, description) VALUES (?, ?, ?, ?)", args: [userId, refundMc, LedgerOperation.EXTRACT_SITE_REFUND, reference] },
|
|
7517
|
-
{ sql: `UPDATE site_extract_jobs SET billed_mc = ?, updated_at = datetime('now') WHERE id = ? AND billed_mc IS NULL`, args: [Math.max(0, netChargeMc), jobId] }
|
|
7518
|
-
]);
|
|
7519
|
-
}
|
|
7520
|
-
|
|
7521
7438
|
// src/inngest/functions/site-extract.ts
|
|
7522
7439
|
var BATCH = 30;
|
|
7523
|
-
function buildArtifacts(job, pages, branding, imageAudit) {
|
|
7524
|
-
const { edges, metrics } = buildLinkGraph(pages, job.startUrl);
|
|
7525
|
-
const issues = computeIssues(pages, metrics);
|
|
7526
|
-
const linkReport = buildLinkReport(edges, [...metrics.values()], job.startUrl);
|
|
7527
|
-
let reportMd = renderIssueReport(job.startUrl, pages, issues, metrics);
|
|
7528
|
-
if (imageAudit) reportMd += `
|
|
7529
|
-
|
|
7530
|
-
${renderImageSection(imageAudit)}`;
|
|
7531
|
-
const pageRows = pages.map((p) => {
|
|
7532
|
-
const { bodyMarkdown: _b, schema: _s, outlinks: _o, ...rest } = p;
|
|
7533
|
-
const m = metrics.get(p.url);
|
|
7534
|
-
return { ...rest, inlinks: m?.inlinks ?? 0, crawlDepth: m?.crawlDepth ?? null, orphan: m?.orphan ?? false };
|
|
7535
|
-
});
|
|
7536
|
-
const jsonl = (rows) => rows.map((r) => JSON.stringify(r)).join("\n");
|
|
7537
|
-
const files = [
|
|
7538
|
-
{ name: "report.md", body: reportMd, type: "text/markdown" },
|
|
7539
|
-
{ name: "issues.json", body: JSON.stringify(issues, null, 2), type: "application/json" },
|
|
7540
|
-
{ name: "pages.jsonl", body: jsonl(pageRows), type: "application/x-ndjson" },
|
|
7541
|
-
{ name: "links.jsonl", body: jsonl(edges), type: "application/x-ndjson" },
|
|
7542
|
-
{ name: "link-metrics.jsonl", body: jsonl([...metrics.values()]), type: "application/x-ndjson" },
|
|
7543
|
-
{ name: "link-report.md", body: renderLinkReport(linkReport), type: "text/markdown" },
|
|
7544
|
-
{ name: "links-summary.json", body: JSON.stringify(linkReport.summary, null, 2), type: "application/json" },
|
|
7545
|
-
{ name: "external-domains.json", body: JSON.stringify(linkReport.externalDomains, null, 2), type: "application/json" }
|
|
7546
|
-
];
|
|
7547
|
-
if (imageAudit) {
|
|
7548
|
-
files.push({ name: "images.jsonl", body: jsonl(imageAudit.rows), type: "application/x-ndjson" });
|
|
7549
|
-
files.push({ name: "images-summary.json", body: JSON.stringify(imageAudit.summary, null, 2), type: "application/json" });
|
|
7550
|
-
}
|
|
7551
|
-
if (branding) files.push({ name: "branding.json", body: JSON.stringify(branding, null, 2), type: "application/json" });
|
|
7552
|
-
return files;
|
|
7553
|
-
}
|
|
7554
7440
|
var siteExtractFn = inngest.createFunction(
|
|
7555
7441
|
{
|
|
7556
7442
|
id: "site-extract",
|
|
@@ -7565,7 +7451,9 @@ var siteExtractFn = inngest.createFunction(
|
|
|
7565
7451
|
await settleExtractJob(jobId, current.userId, heldMc, 0, "crawl failed refund").catch(() => {
|
|
7566
7452
|
});
|
|
7567
7453
|
}
|
|
7568
|
-
|
|
7454
|
+
const rawErr = String(event?.data?.error?.message ?? "crawl failed");
|
|
7455
|
+
const friendly = /FUNCTION_INVOCATION_FAILED|out of memory|heap/i.test(rawErr) ? "Result assembly failed on our side \u2014 your crawl data is safe and the job can be re-finalized without re-crawling. Contact support if this persists." : rawErr;
|
|
7456
|
+
await failExtractJob(jobId, friendly).catch(() => {
|
|
7569
7457
|
});
|
|
7570
7458
|
}
|
|
7571
7459
|
},
|
|
@@ -7641,11 +7529,8 @@ var siteExtractFn = inngest.createFunction(
|
|
|
7641
7529
|
return auditImages(pages, { concurrency: 12, timeoutMs: 12e3 });
|
|
7642
7530
|
}) : null;
|
|
7643
7531
|
const artifacts = await step.run("finalize", async () => {
|
|
7644
|
-
const
|
|
7645
|
-
const
|
|
7646
|
-
const files = buildArtifacts(job, pages, branding, imageAudit);
|
|
7647
|
-
const stored = [];
|
|
7648
|
-
for (const f of files) stored.push(await store.put(`extract/${jobId}/${f.name}`, f.body, f.type));
|
|
7532
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-UKE273TV.js");
|
|
7533
|
+
const stored = await assembleExtractArtifacts(job, { branding, imageAudit });
|
|
7649
7534
|
await completeExtractJob(jobId, stored);
|
|
7650
7535
|
return stored;
|
|
7651
7536
|
});
|
|
@@ -11961,8 +11846,13 @@ function verifySession(token) {
|
|
|
11961
11846
|
}
|
|
11962
11847
|
|
|
11963
11848
|
// src/api/memory.ts
|
|
11964
|
-
var MEMORY_BASE_URL = () => (process.env.MCP_MEMORY_BASE_URL ?? "https://
|
|
11849
|
+
var MEMORY_BASE_URL = () => (process.env.MCP_MEMORY_BASE_URL ?? "https://memory.mcpscraper.dev").replace(/\/$/, "");
|
|
11965
11850
|
var ADMIN_KEY = () => process.env.MCP_MEMORY_ADMIN_KEY?.trim() ?? "";
|
|
11851
|
+
function parseMemoryRpcBody(text) {
|
|
11852
|
+
const dataLine = text.split("\n").find((line) => line.startsWith("data:"));
|
|
11853
|
+
const payload = dataLine ? dataLine.slice(5).trim() : text;
|
|
11854
|
+
return JSON.parse(payload);
|
|
11855
|
+
}
|
|
11966
11856
|
function isMemoryOperator(email) {
|
|
11967
11857
|
if (!email) return false;
|
|
11968
11858
|
const ops = (process.env.MEMORY_OPERATOR_IDENTITIES ?? "").split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
@@ -11990,15 +11880,34 @@ function decryptMemoryKey(stored) {
|
|
|
11990
11880
|
}
|
|
11991
11881
|
async function memoryCall(toolName, args, userMemoryKey) {
|
|
11992
11882
|
try {
|
|
11993
|
-
const res = await fetch(`${MEMORY_BASE_URL()}/
|
|
11883
|
+
const res = await fetch(`${MEMORY_BASE_URL()}/mcp`, {
|
|
11994
11884
|
method: "POST",
|
|
11995
|
-
headers: {
|
|
11996
|
-
|
|
11885
|
+
headers: {
|
|
11886
|
+
"content-type": "application/json",
|
|
11887
|
+
accept: "application/json, text/event-stream",
|
|
11888
|
+
authorization: `Bearer ${userMemoryKey}`
|
|
11889
|
+
},
|
|
11890
|
+
body: JSON.stringify({
|
|
11891
|
+
jsonrpc: "2.0",
|
|
11892
|
+
id: 1,
|
|
11893
|
+
method: "tools/call",
|
|
11894
|
+
params: { name: toolName, arguments: args }
|
|
11895
|
+
})
|
|
11997
11896
|
});
|
|
11998
|
-
const
|
|
11999
|
-
if (!res.ok) return { ok: false, error:
|
|
12000
|
-
|
|
12001
|
-
return { ok: false, error: body
|
|
11897
|
+
const text = await res.text();
|
|
11898
|
+
if (!res.ok) return { ok: false, error: `memory ${toolName} failed (${res.status})` };
|
|
11899
|
+
const body = parseMemoryRpcBody(text);
|
|
11900
|
+
if (body.error) return { ok: false, error: body.error.message ?? `memory ${toolName} failed` };
|
|
11901
|
+
if (body.result?.structuredContent) return body.result.structuredContent;
|
|
11902
|
+
const textContent = body.result?.content?.find((c) => c.type === "text")?.text;
|
|
11903
|
+
if (textContent) {
|
|
11904
|
+
try {
|
|
11905
|
+
return JSON.parse(textContent);
|
|
11906
|
+
} catch {
|
|
11907
|
+
return { ok: false, error: textContent };
|
|
11908
|
+
}
|
|
11909
|
+
}
|
|
11910
|
+
return { ok: false, error: `memory ${toolName} returned no result` };
|
|
12002
11911
|
} catch (err) {
|
|
12003
11912
|
return { ok: false, error: err?.message ?? "memory call failed" };
|
|
12004
11913
|
}
|
|
@@ -12078,13 +11987,16 @@ var videoApp = new Hono9();
|
|
|
12078
11987
|
var AnalyzeBodySchema = z17.object({
|
|
12079
11988
|
sourceUrl: z17.string().trim().url("sourceUrl must be a direct video file URL"),
|
|
12080
11989
|
intervalS: z17.number().min(1).max(30).optional(),
|
|
12081
|
-
maxFrames: z17.number().int().min(1).max(
|
|
11990
|
+
maxFrames: z17.number().int().min(1).max(480).optional(),
|
|
12082
11991
|
detail: z17.enum(["fast", "standard", "deep"]).optional(),
|
|
12083
11992
|
vault: z17.string().trim().min(1).optional()
|
|
12084
11993
|
});
|
|
12085
11994
|
function invalidRequest5(message) {
|
|
12086
11995
|
return { error_code: "invalid_request", message };
|
|
12087
11996
|
}
|
|
11997
|
+
function tiersFor(frames) {
|
|
11998
|
+
return Math.ceil(Math.min(Math.max(frames, 1), 480) / 120);
|
|
11999
|
+
}
|
|
12088
12000
|
videoApp.post("/analyze", createApiKeyAuth(), async (c) => {
|
|
12089
12001
|
const parsed = AnalyzeBodySchema.safeParse(await c.req.json().catch(() => ({})));
|
|
12090
12002
|
if (!parsed.success) return c.json(invalidRequest5(parsed.error.issues[0]?.message ?? "invalid request"), 400);
|
|
@@ -12092,21 +12004,24 @@ videoApp.post("/analyze", createApiKeyAuth(), async (c) => {
|
|
|
12092
12004
|
const user = c.get("user");
|
|
12093
12005
|
const { key: memKey, error: memErr } = await getOrCreateUserMemoryKey(user);
|
|
12094
12006
|
if (!memKey) return c.json({ error_code: "memory_unavailable", message: memErr ?? "memory unavailable" }, 502);
|
|
12095
|
-
const
|
|
12096
|
-
|
|
12007
|
+
const requestedFrames = Math.min(Math.max(body.maxFrames ?? 120, 1), 480);
|
|
12008
|
+
const tiers = tiersFor(requestedFrames);
|
|
12009
|
+
const holdMc = tiers * MC_COSTS.video_analysis;
|
|
12010
|
+
const { ok, balance_mc } = await debitMc(user.id, holdMc, LedgerOperation.VIDEO_ANALYSIS, body.sourceUrl);
|
|
12011
|
+
if (!ok) return c.json(insufficientBalanceResponse(balance_mc, holdMc), 402);
|
|
12097
12012
|
const started = await memoryCall(
|
|
12098
12013
|
"videoAnalyzeStartTool",
|
|
12099
12014
|
{
|
|
12100
12015
|
sourceUrl: body.sourceUrl,
|
|
12101
12016
|
intervalS: body.intervalS ?? 2,
|
|
12102
|
-
maxFrames:
|
|
12017
|
+
maxFrames: requestedFrames,
|
|
12103
12018
|
detail: body.detail ?? "standard",
|
|
12104
12019
|
vault: body.vault ?? "Library"
|
|
12105
12020
|
},
|
|
12106
12021
|
memKey
|
|
12107
12022
|
);
|
|
12108
12023
|
if (!started.ok || !started.runId) {
|
|
12109
|
-
await creditMc(user.id,
|
|
12024
|
+
await creditMc(user.id, holdMc, LedgerOperation.VIDEO_ANALYSIS_REFUND, `start-failed:${body.sourceUrl}`);
|
|
12110
12025
|
return c.json({ error_code: "video_start_failed", message: started.error ?? "could not start analysis" }, 502);
|
|
12111
12026
|
}
|
|
12112
12027
|
return c.json({
|
|
@@ -12125,11 +12040,30 @@ videoApp.post("/status", createApiKeyAuth(), async (c) => {
|
|
|
12125
12040
|
if (!memKey) return c.json({ error_code: "memory_unavailable", message: memErr ?? "memory unavailable" }, 502);
|
|
12126
12041
|
const st = await memoryCall("videoAnalyzeStatusTool", { runId }, memKey);
|
|
12127
12042
|
if (!st.ok) return c.json({ error_code: "not_found", message: st.error ?? "run not found" }, 404);
|
|
12043
|
+
const requestedTiers = tiersFor(st.maxFrames ?? 120);
|
|
12044
|
+
let reconciliation = null;
|
|
12128
12045
|
if (st.status === "failed") {
|
|
12046
|
+
const refundMc = requestedTiers * MC_COSTS.video_analysis;
|
|
12129
12047
|
const refundOp = `${LedgerOperation.VIDEO_ANALYSIS_REFUND}:${runId}`;
|
|
12130
12048
|
if (!await ledgerExistsForOperation(user.id, refundOp)) {
|
|
12131
|
-
await creditMc(user.id,
|
|
12049
|
+
await creditMc(user.id, refundMc, refundOp, `run-failed:${runId}`);
|
|
12050
|
+
}
|
|
12051
|
+
reconciliation = { billedMc: requestedTiers * MC_COSTS.video_analysis, refundedMc: refundMc, effectiveFrames: null };
|
|
12052
|
+
}
|
|
12053
|
+
if (st.status === "done") {
|
|
12054
|
+
const effectiveTiers = tiersFor(st.frameCount ?? 120);
|
|
12055
|
+
const diff = requestedTiers - effectiveTiers;
|
|
12056
|
+
if (diff > 0) {
|
|
12057
|
+
const adjustOp = `${LedgerOperation.VIDEO_ANALYSIS_ADJUST}:${runId}`;
|
|
12058
|
+
if (!await ledgerExistsForOperation(user.id, adjustOp)) {
|
|
12059
|
+
await creditMc(user.id, diff * MC_COSTS.video_analysis, adjustOp, `tier-reconcile:${runId}`);
|
|
12060
|
+
}
|
|
12132
12061
|
}
|
|
12062
|
+
reconciliation = {
|
|
12063
|
+
billedMc: requestedTiers * MC_COSTS.video_analysis,
|
|
12064
|
+
refundedMc: Math.max(diff, 0) * MC_COSTS.video_analysis,
|
|
12065
|
+
effectiveFrames: st.frameCount ?? null
|
|
12066
|
+
};
|
|
12133
12067
|
}
|
|
12134
12068
|
return c.json({
|
|
12135
12069
|
ok: true,
|
|
@@ -12138,7 +12072,8 @@ videoApp.post("/status", createApiKeyAuth(), async (c) => {
|
|
|
12138
12072
|
progress: st.progress ?? null,
|
|
12139
12073
|
frameCount: st.frameCount ?? null,
|
|
12140
12074
|
...st.status === "done" ? { artifactPath: st.artifactPath ?? null, report: st.report ?? null } : {},
|
|
12141
|
-
...st.error ? { error: st.error } : {}
|
|
12075
|
+
...st.error ? { error: st.error } : {},
|
|
12076
|
+
...reconciliation ? { reconciliation } : {}
|
|
12142
12077
|
});
|
|
12143
12078
|
});
|
|
12144
12079
|
|
|
@@ -15070,6 +15005,7 @@ mcpApp.all("/", async (c) => {
|
|
|
15070
15005
|
const server = buildPaaExtractorMcpServer(executor, { savesReportsLocally: false, ownerId: hashOwnerId(callerKey) });
|
|
15071
15006
|
registerSerpIntelligenceCaptureTools(server, executor);
|
|
15072
15007
|
registerBrowserAgentMcpTools(server, { baseUrl, apiKey: callerKey, consoleBaseUrl, savesReportsLocally: false });
|
|
15008
|
+
registerMemoryMcpTools(server, new MemoryMcpToolExecutor(baseUrl, callerKey));
|
|
15073
15009
|
await server.connect(transport);
|
|
15074
15010
|
return transport.handleRequest(c.req.raw);
|
|
15075
15011
|
} catch {
|
|
@@ -19458,6 +19394,15 @@ app.get("/memory/vaults", auth2, async (c) => {
|
|
|
19458
19394
|
return c.json({ ok: false, error: err instanceof Error ? err.message : "could not load vaults" }, 502);
|
|
19459
19395
|
}
|
|
19460
19396
|
});
|
|
19397
|
+
app.post("/memory/mcp-call", auth2, async (c) => {
|
|
19398
|
+
const user = c.get("user");
|
|
19399
|
+
const body = await c.req.json().catch(() => ({}));
|
|
19400
|
+
if (!body.toolName) return c.json({ ok: false, error: "toolName is required" }, 400);
|
|
19401
|
+
const { key, error } = await getOrCreateUserMemoryKey(user);
|
|
19402
|
+
if (!key) return c.json({ ok: false, error: error ?? "memory unavailable" }, 502);
|
|
19403
|
+
const result = await memoryCall(body.toolName, body.args ?? {}, key);
|
|
19404
|
+
return c.json(result);
|
|
19405
|
+
});
|
|
19461
19406
|
app.get("/memory/approved-senders", auth2, async (c) => {
|
|
19462
19407
|
const { key, error } = await getOrCreateUserMemoryKey(c.get("user"));
|
|
19463
19408
|
if (!key) return c.json({ ok: false, error: error ?? "memory unavailable" }, 502);
|
|
@@ -20522,7 +20467,7 @@ app.get("/cron/tick", async (c) => {
|
|
|
20522
20467
|
if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
|
|
20523
20468
|
return c.json({ error: "Unauthorized" }, 401);
|
|
20524
20469
|
}
|
|
20525
|
-
const { drainQueue } = await import("./worker-
|
|
20470
|
+
const { drainQueue } = await import("./worker-RVZXIALX.js");
|
|
20526
20471
|
const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
|
|
20527
20472
|
const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
|
|
20528
20473
|
const [results, sweepResult, reapResult, expiredResult, blobCleanup] = await Promise.all([
|
|
@@ -20534,6 +20479,35 @@ app.get("/cron/tick", async (c) => {
|
|
|
20534
20479
|
]);
|
|
20535
20480
|
return c.json({ drained: results.length, results, sweepResult, reaped: reapResult, expired: expiredResult, blobCleanup, workflowDispatch: workflowDispatchResult });
|
|
20536
20481
|
});
|
|
20482
|
+
app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
20483
|
+
const secret2 = c.req.header("authorization");
|
|
20484
|
+
if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
|
|
20485
|
+
return c.json({ error: "Unauthorized" }, 401);
|
|
20486
|
+
}
|
|
20487
|
+
const jobId = c.req.param("id");
|
|
20488
|
+
const { getExtractJob: getExtractJob2, completeExtractJob: completeExtractJob2 } = await import("./site-extract-repository-2MQBAOX5.js");
|
|
20489
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-UKE273TV.js");
|
|
20490
|
+
const job = await getExtractJob2(jobId);
|
|
20491
|
+
if (!job) return c.json({ error: "job not found" }, 404);
|
|
20492
|
+
const stored = await assembleExtractArtifacts(job, {});
|
|
20493
|
+
await completeExtractJob2(jobId, stored);
|
|
20494
|
+
let settlement = "already_settled_or_refunded";
|
|
20495
|
+
if (job.billedMc == null && job.userId != null) {
|
|
20496
|
+
const { settleExtractJob: settleExtractJob2, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-2MQBAOX5.js");
|
|
20497
|
+
const heldMc = Number(job.options.heldMc ?? 0);
|
|
20498
|
+
const successful = await countSuccessfulPages2(jobId);
|
|
20499
|
+
const usedMc = Math.min(successful * MC_COSTS.page_scrape, heldMc);
|
|
20500
|
+
let host = "site";
|
|
20501
|
+
try {
|
|
20502
|
+
host = new URL(job.startUrl).hostname;
|
|
20503
|
+
} catch {
|
|
20504
|
+
}
|
|
20505
|
+
await settleExtractJob2(jobId, job.userId, heldMc - usedMc, usedMc, host);
|
|
20506
|
+
settlement = `settled: billed ${usedMc} mc, refunded ${heldMc - usedMc} mc`;
|
|
20507
|
+
}
|
|
20508
|
+
const bundle = stored.find((a) => a.key.endsWith("bundle.zip"));
|
|
20509
|
+
return c.json({ ok: true, jobId, artifacts: stored.length, settlement, bundleUrl: bundle?.url ?? null, bundleBytes: bundle?.bytes ?? null });
|
|
20510
|
+
});
|
|
20537
20511
|
app.on(["GET", "POST", "PUT"], "/api/inngest", serveInngest({ client: inngest, functions: [siteAuditFn, siteExtractFn] }));
|
|
20538
20512
|
app.route("/api/internal/site-architecture-auditor", siteAuditApp);
|
|
20539
20513
|
app.route("/api/internal/memory", internalMemoryApp);
|
|
@@ -20675,4 +20649,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
20675
20649
|
export {
|
|
20676
20650
|
app
|
|
20677
20651
|
};
|
|
20678
|
-
//# sourceMappingURL=server-
|
|
20652
|
+
//# sourceMappingURL=server-Z4WKTE6F.js.map
|