mcp-scraper 0.50.0 → 0.51.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/README.md +11 -3
- package/dist/bin/api-server.cjs +268 -39
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- 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 +112 -30
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/chunk-73MUQSWC.js +7 -0
- package/dist/chunk-73MUQSWC.js.map +1 -0
- package/dist/{chunk-44LNKZTE.js → chunk-O63VVCCE.js} +113 -31
- package/dist/chunk-O63VVCCE.js.map +1 -0
- package/dist/editorial-reading-room/assets/app.js +62 -0
- package/dist/editorial-reading-room/assets/index.html +8 -0
- package/dist/editorial-reading-room/assets/styles.css +39 -0
- package/dist/{server-3ND2EXYO.js → server-IGIIEHXY.js} +157 -10
- package/dist/{server-3ND2EXYO.js.map → server-IGIIEHXY.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-44LNKZTE.js.map +0 -1
- package/dist/chunk-C7NN57WH.js +0 -7
- package/dist/chunk-C7NN57WH.js.map +0 -1
|
@@ -32,6 +32,39 @@ function escapeHtml(value = "") {
|
|
|
32
32
|
.replace(/"/g, """);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function socialImage(article = null) {
|
|
36
|
+
return article?.ogImage || article?.image || state.data.site.ogImage || null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function setMeta(selector, attribute, value) {
|
|
40
|
+
const element = document.querySelector(selector);
|
|
41
|
+
if (!element) return;
|
|
42
|
+
if (value) element.setAttribute(attribute, value);
|
|
43
|
+
else element.removeAttribute(attribute);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function updateSocialMeta(article = null) {
|
|
47
|
+
const title = article ? `${article.title} — ${state.data.site.title}` : state.data.site.title;
|
|
48
|
+
const description = article?.summary || state.data.deck || state.data.site.heroTitle;
|
|
49
|
+
const image = socialImage(article);
|
|
50
|
+
setMeta('meta[property="og:type"]', "content", article ? "article" : "website");
|
|
51
|
+
setMeta('meta[property="og:title"]', "content", title);
|
|
52
|
+
setMeta('meta[property="og:description"]', "content", description);
|
|
53
|
+
setMeta('meta[name="twitter:title"]', "content", title);
|
|
54
|
+
setMeta('meta[name="twitter:description"]', "content", description);
|
|
55
|
+
setMeta('meta[property="og:image"]', "content", image?.url || "");
|
|
56
|
+
setMeta('meta[property="og:image:alt"]', "content", image?.alt || "");
|
|
57
|
+
setMeta('meta[property="og:image:width"]', "content", image?.width ? String(image.width) : "");
|
|
58
|
+
setMeta('meta[property="og:image:height"]', "content", image?.height ? String(image.height) : "");
|
|
59
|
+
setMeta('meta[name="twitter:image"]', "content", image?.url || "");
|
|
60
|
+
setMeta('meta[name="twitter:image:alt"]', "content", image?.alt || "");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function imageMarkup(image, className) {
|
|
64
|
+
if (!image) return "";
|
|
65
|
+
return `<img class="${className}" src="${escapeHtml(image.url)}" alt="${escapeHtml(image.alt)}" loading="lazy">`;
|
|
66
|
+
}
|
|
67
|
+
|
|
35
68
|
function setTypeMode() {
|
|
36
69
|
const mode = typeModes[state.typeIndex % typeModes.length];
|
|
37
70
|
if (mode === "default") document.documentElement.removeAttribute("data-type");
|
|
@@ -132,6 +165,7 @@ function renderHome() {
|
|
|
132
165
|
elements.article.hidden = true;
|
|
133
166
|
elements.progress.style.width = "0";
|
|
134
167
|
document.title = state.data.site.title;
|
|
168
|
+
updateSocialMeta();
|
|
135
169
|
document.querySelector("#masthead-product").textContent = state.data.site.product;
|
|
136
170
|
document.querySelector("#masthead-title").textContent = state.data.site.edition;
|
|
137
171
|
document.querySelector("#edition-label").textContent = state.data.site.editionLabel;
|
|
@@ -151,6 +185,7 @@ function renderHome() {
|
|
|
151
185
|
.map(
|
|
152
186
|
(article) => `<article class="feature-card">
|
|
153
187
|
<button data-article="${article.slug}">
|
|
188
|
+
${imageMarkup(article.image, "feature-card-image")}
|
|
154
189
|
<p class="card-kicker">${escapeHtml(article.kicker)}</p>
|
|
155
190
|
<h2>${escapeHtml(article.title)}</h2>
|
|
156
191
|
<p>${escapeHtml(article.summary)}</p>
|
|
@@ -190,6 +225,7 @@ function renderArticle(article) {
|
|
|
190
225
|
elements.home.hidden = true;
|
|
191
226
|
elements.article.hidden = false;
|
|
192
227
|
document.title = `${article.title} — ${state.data.site.title}`;
|
|
228
|
+
updateSocialMeta(article);
|
|
193
229
|
document.querySelector("#article-category").textContent = article.category;
|
|
194
230
|
document.querySelector("#article-kicker").textContent = article.kicker;
|
|
195
231
|
document.querySelector("#article-title").textContent = article.title;
|
|
@@ -199,6 +235,32 @@ function renderArticle(article) {
|
|
|
199
235
|
document.querySelector("#article-revision").textContent = article.revision
|
|
200
236
|
? `Revision ${article.revision}`
|
|
201
237
|
: article.sourceType || "Source material";
|
|
238
|
+
const imageFigure = document.querySelector("#article-image");
|
|
239
|
+
const imageElement = document.querySelector("#article-image-src");
|
|
240
|
+
const imageCaption = document.querySelector("#article-image-caption");
|
|
241
|
+
const imageCaptionText = document.querySelector("#article-image-caption-text");
|
|
242
|
+
const imageSource = document.querySelector("#article-image-source");
|
|
243
|
+
if (article.image) {
|
|
244
|
+
imageFigure.hidden = false;
|
|
245
|
+
imageElement.src = article.image.url;
|
|
246
|
+
imageElement.alt = article.image.alt;
|
|
247
|
+
imageCaptionText.textContent = [article.image.caption, article.image.credit].filter(Boolean).join(" — ");
|
|
248
|
+
if (article.image.sourceUrl) {
|
|
249
|
+
imageSource.href = article.image.sourceUrl;
|
|
250
|
+
imageSource.hidden = false;
|
|
251
|
+
} else {
|
|
252
|
+
imageSource.removeAttribute("href");
|
|
253
|
+
imageSource.hidden = true;
|
|
254
|
+
}
|
|
255
|
+
imageCaption.hidden = !imageCaptionText.textContent && !article.image.sourceUrl;
|
|
256
|
+
} else {
|
|
257
|
+
imageFigure.hidden = true;
|
|
258
|
+
imageElement.removeAttribute("src");
|
|
259
|
+
imageElement.alt = "";
|
|
260
|
+
imageCaptionText.textContent = "";
|
|
261
|
+
imageSource.removeAttribute("href");
|
|
262
|
+
imageSource.hidden = true;
|
|
263
|
+
}
|
|
202
264
|
document.querySelector("#article-body").innerHTML = article.html;
|
|
203
265
|
document.querySelector("#article-source").textContent = article.sourceLabel;
|
|
204
266
|
renderDesktopJumps(article);
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
content="A mobile-first editorial reading room."
|
|
9
9
|
/>
|
|
10
10
|
<meta name="theme-color" content="#f5f1e8" />
|
|
11
|
+
<!--__READING_ROOM_SOCIAL_META__-->
|
|
11
12
|
<title>Editorial Reading Room</title>
|
|
12
13
|
<style>/*__READING_ROOM_STYLES__*/</style>
|
|
13
14
|
</head>
|
|
@@ -99,6 +100,13 @@
|
|
|
99
100
|
<span id="article-word-count"></span>
|
|
100
101
|
<span id="article-revision"></span>
|
|
101
102
|
</div>
|
|
103
|
+
<figure class="article-image" id="article-image" hidden>
|
|
104
|
+
<img id="article-image-src" alt="" />
|
|
105
|
+
<figcaption id="article-image-caption">
|
|
106
|
+
<span id="article-image-caption-text"></span>
|
|
107
|
+
<a id="article-image-source" target="_blank" rel="noopener noreferrer">Image source</a>
|
|
108
|
+
</figcaption>
|
|
109
|
+
</figure>
|
|
102
110
|
</header>
|
|
103
111
|
<div class="article-body" id="article-body"></div>
|
|
104
112
|
<footer class="article-source">
|
|
@@ -277,6 +277,14 @@ a {
|
|
|
277
277
|
text-align: left;
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
+
.feature-card-image {
|
|
281
|
+
width: 100%;
|
|
282
|
+
aspect-ratio: 16 / 9;
|
|
283
|
+
margin-bottom: 20px;
|
|
284
|
+
border: 1px solid var(--rule);
|
|
285
|
+
object-fit: cover;
|
|
286
|
+
}
|
|
287
|
+
|
|
280
288
|
.card-kicker {
|
|
281
289
|
margin: 0 0 18px;
|
|
282
290
|
color: var(--accent);
|
|
@@ -594,6 +602,37 @@ body.drawer-open .drawer-backdrop {
|
|
|
594
602
|
text-transform: uppercase;
|
|
595
603
|
}
|
|
596
604
|
|
|
605
|
+
.article-image {
|
|
606
|
+
margin: 34px 0 0;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.article-image img {
|
|
610
|
+
display: block;
|
|
611
|
+
width: 100%;
|
|
612
|
+
max-height: 680px;
|
|
613
|
+
border: 1px solid var(--rule);
|
|
614
|
+
object-fit: cover;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.article-image figcaption {
|
|
618
|
+
margin-top: 9px;
|
|
619
|
+
color: var(--muted);
|
|
620
|
+
font-size: 12px;
|
|
621
|
+
line-height: 1.45;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.article-image figcaption a {
|
|
625
|
+
margin-left: 0.45em;
|
|
626
|
+
color: inherit;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
.article-body img {
|
|
630
|
+
display: block;
|
|
631
|
+
max-width: 100%;
|
|
632
|
+
height: auto;
|
|
633
|
+
margin: 1.8em auto;
|
|
634
|
+
}
|
|
635
|
+
|
|
597
636
|
.article-body {
|
|
598
637
|
padding-top: 28px;
|
|
599
638
|
font-family: var(--serif);
|
|
@@ -158,7 +158,7 @@ import {
|
|
|
158
158
|
resolveDeploymentProfile,
|
|
159
159
|
resolveLocalSourcebookSchemaType,
|
|
160
160
|
transcribeMediaUrl
|
|
161
|
-
} from "./chunk-
|
|
161
|
+
} from "./chunk-O63VVCCE.js";
|
|
162
162
|
import {
|
|
163
163
|
auditImageUrls,
|
|
164
164
|
auditImages,
|
|
@@ -214,7 +214,7 @@ import {
|
|
|
214
214
|
} from "./chunk-3ZUBQQPQ.js";
|
|
215
215
|
import {
|
|
216
216
|
PACKAGE_VERSION
|
|
217
|
-
} from "./chunk-
|
|
217
|
+
} from "./chunk-73MUQSWC.js";
|
|
218
218
|
import {
|
|
219
219
|
abandonExtractSettlement,
|
|
220
220
|
countSuccessfulPages,
|
|
@@ -20000,6 +20000,34 @@ import { Hono as Hono11 } from "hono";
|
|
|
20000
20000
|
import { z as z21 } from "zod";
|
|
20001
20001
|
|
|
20002
20002
|
// src/api/reddit-trending.ts
|
|
20003
|
+
var PARSE_REDDIT_SEARCH = `(() => {
|
|
20004
|
+
const txt = el => ((el && el.innerText) || '').trim();
|
|
20005
|
+
const bodyText = (document.body && document.body.innerText) || '';
|
|
20006
|
+
const blocked = /whoa there|blocked by network|you've been blocked|network (policy|security)|log in to your reddit account/i.test(bodyText);
|
|
20007
|
+
const listing = document.querySelector('.search-result-listing');
|
|
20008
|
+
const rows = [];
|
|
20009
|
+
document.querySelectorAll('.search-result.search-result-link').forEach(r => {
|
|
20010
|
+
const titleEl = r.querySelector('header.search-result-header a.search-title');
|
|
20011
|
+
rows.push({
|
|
20012
|
+
title: txt(titleEl),
|
|
20013
|
+
url: (titleEl && titleEl.getAttribute('href')) || '',
|
|
20014
|
+
subreddit: txt(r.querySelector('a.search-subreddit-link')),
|
|
20015
|
+
scoreText: txt(r.querySelector('.search-score')),
|
|
20016
|
+
commentsText: txt(r.querySelector('a.search-comments')),
|
|
20017
|
+
ageText: txt(r.querySelector('.search-time time')),
|
|
20018
|
+
});
|
|
20019
|
+
});
|
|
20020
|
+
return { blocked: blocked, listingFound: Boolean(listing), rowCount: rows.length, rows: rows };
|
|
20021
|
+
})()`;
|
|
20022
|
+
function buildRedditSearchUrl(topic, subreddit, window2 = "month") {
|
|
20023
|
+
const base = subreddit ? `https://old.reddit.com/r/${encodeURIComponent(subreddit)}/search` : "https://old.reddit.com/search";
|
|
20024
|
+
const params = new URLSearchParams();
|
|
20025
|
+
params.set("q", topic);
|
|
20026
|
+
params.set("sort", "top");
|
|
20027
|
+
params.set("t", window2);
|
|
20028
|
+
if (subreddit) params.set("restrict_sr", "on");
|
|
20029
|
+
return `${base}?${params.toString()}`;
|
|
20030
|
+
}
|
|
20003
20031
|
function buildSerpQuery(topic, subreddit) {
|
|
20004
20032
|
const scope = subreddit ? `site:reddit.com/r/${subreddit}` : "site:reddit.com";
|
|
20005
20033
|
return `${scope} ${topic}`.trim();
|
|
@@ -20062,6 +20090,32 @@ function canonicalThreadUrl(href) {
|
|
|
20062
20090
|
function engagementScore(score, commentCount) {
|
|
20063
20091
|
return score + 2 * commentCount;
|
|
20064
20092
|
}
|
|
20093
|
+
function normalizeSearchRows(rows) {
|
|
20094
|
+
if (!Array.isArray(rows)) return [];
|
|
20095
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20096
|
+
const out = [];
|
|
20097
|
+
for (const raw of rows) {
|
|
20098
|
+
if (!raw || typeof raw !== "object") continue;
|
|
20099
|
+
const r = raw;
|
|
20100
|
+
const url = canonicalThreadUrl(r.url);
|
|
20101
|
+
const title = typeof r.title === "string" ? r.title.trim() : "";
|
|
20102
|
+
if (!url || !title || seen.has(url)) continue;
|
|
20103
|
+
seen.add(url);
|
|
20104
|
+
const score = parseCountText(r.scoreText);
|
|
20105
|
+
const commentCount = parseCountText(r.commentsText);
|
|
20106
|
+
out.push({
|
|
20107
|
+
title,
|
|
20108
|
+
url,
|
|
20109
|
+
subreddit: typeof r.subreddit === "string" ? r.subreddit.trim() : "",
|
|
20110
|
+
score,
|
|
20111
|
+
commentCount,
|
|
20112
|
+
engagementScore: engagementScore(score, commentCount),
|
|
20113
|
+
ageText: typeof r.ageText === "string" ? r.ageText.trim() : "",
|
|
20114
|
+
topQuestions: []
|
|
20115
|
+
});
|
|
20116
|
+
}
|
|
20117
|
+
return out;
|
|
20118
|
+
}
|
|
20065
20119
|
var INTERROGATIVE_STARTERS = /* @__PURE__ */ new Set([
|
|
20066
20120
|
"what",
|
|
20067
20121
|
"whats",
|
|
@@ -20213,8 +20267,8 @@ var PARSE_REDDIT = `(() => {
|
|
|
20213
20267
|
});
|
|
20214
20268
|
return { title: title, author: author, score: score, postBody: postBody, blocked: blocked, numComments: comments.length, comments: comments };
|
|
20215
20269
|
})()`;
|
|
20216
|
-
async function scrapeOldRedditWithRetries(url, script, accept) {
|
|
20217
|
-
for (let attempt = 0; attempt <
|
|
20270
|
+
async function scrapeOldRedditWithRetries(url, script, accept, maxAttempts = 4) {
|
|
20271
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
20218
20272
|
const backupAttempt = attempt === 3;
|
|
20219
20273
|
if (backupAttempt && !backupProxyAvailable()) break;
|
|
20220
20274
|
const proxyId = backupAttempt ? await createBackupProxyIdSafe(browserServiceApiKey(), attempt) : await residentialProxyId(attempt);
|
|
@@ -20330,6 +20384,9 @@ redditApp.post("/trending", createApiKeyAuth(), async (c) => {
|
|
|
20330
20384
|
if (!ok) return c.json(insufficientBalanceResponse(balance_mc, MC_COSTS.reddit_thread), 402);
|
|
20331
20385
|
discoveryDebited = true;
|
|
20332
20386
|
let candidates = [];
|
|
20387
|
+
let discoverySource = "google_serp";
|
|
20388
|
+
let primaryDiscoveryDegraded = false;
|
|
20389
|
+
let primaryDegradationReasons = [];
|
|
20333
20390
|
try {
|
|
20334
20391
|
const serp = await harvest({
|
|
20335
20392
|
query: serpQuery,
|
|
@@ -20343,14 +20400,59 @@ redditApp.post("/trending", createApiKeyAuth(), async (c) => {
|
|
|
20343
20400
|
softDeadlineMs
|
|
20344
20401
|
});
|
|
20345
20402
|
candidates = extractRedditThreadUrls(serp.organicResults, body.maxThreads);
|
|
20403
|
+
primaryDiscoveryDegraded = serp.diagnostics?.degradedResult === true;
|
|
20404
|
+
primaryDegradationReasons = Array.isArray(serp.diagnostics?.degradationReasons) ? serp.diagnostics.degradationReasons.filter((reason) => typeof reason === "string") : [];
|
|
20346
20405
|
} catch {
|
|
20347
20406
|
candidates = [];
|
|
20407
|
+
primaryDiscoveryDegraded = true;
|
|
20408
|
+
primaryDegradationReasons = ["primary_serp_failed"];
|
|
20409
|
+
}
|
|
20410
|
+
if (candidates.length === 0) {
|
|
20411
|
+
const fallback = await scrapeOldRedditWithRetries(
|
|
20412
|
+
buildRedditSearchUrl(body.topic, subreddit, body.window),
|
|
20413
|
+
PARSE_REDDIT_SEARCH,
|
|
20414
|
+
(data) => !data.blocked && data.listingFound,
|
|
20415
|
+
2
|
|
20416
|
+
);
|
|
20417
|
+
if (fallback) {
|
|
20418
|
+
candidates = normalizeSearchRows(fallback.data.rows).slice(0, body.maxThreads).map((thread) => ({ title: thread.title, url: thread.url, subreddit: thread.subreddit.replace(/^r\//i, "") }));
|
|
20419
|
+
discoverySource = "reddit_search_fallback";
|
|
20420
|
+
} else {
|
|
20421
|
+
discoverySource = "none";
|
|
20422
|
+
}
|
|
20348
20423
|
}
|
|
20349
20424
|
if (candidates.length === 0) {
|
|
20350
20425
|
await creditMc(user.id, MC_COSTS.reddit_thread, LedgerOperation.REDDIT_THREAD_REFUND, "no reddit threads discovered");
|
|
20351
20426
|
discoveryRefunded = true;
|
|
20352
|
-
|
|
20353
|
-
|
|
20427
|
+
const degradedResult = discoverySource === "none";
|
|
20428
|
+
const degradationReasons = degradedResult ? [.../* @__PURE__ */ new Set([...primaryDegradationReasons, "reddit_fallback_empty_or_blocked"])] : [];
|
|
20429
|
+
const result2 = {
|
|
20430
|
+
topic: body.topic,
|
|
20431
|
+
subreddit: subreddit ?? null,
|
|
20432
|
+
window: body.window === "week" ? "7d" : "30d",
|
|
20433
|
+
totals: trendingTotals([]),
|
|
20434
|
+
rankedThreads: [],
|
|
20435
|
+
questions: [],
|
|
20436
|
+
threadsScraped: 0,
|
|
20437
|
+
candidatesFound: 0,
|
|
20438
|
+
partial: false,
|
|
20439
|
+
searchQuery: serpQuery,
|
|
20440
|
+
discoverySource,
|
|
20441
|
+
resultQuality: degradedResult ? "degraded" : "complete",
|
|
20442
|
+
degradedResult,
|
|
20443
|
+
degradationReasons,
|
|
20444
|
+
retryRecommended: degradedResult,
|
|
20445
|
+
billingRefunded: true
|
|
20446
|
+
};
|
|
20447
|
+
await logRequestEvent({
|
|
20448
|
+
userId: user.id,
|
|
20449
|
+
source: "reddit_trending",
|
|
20450
|
+
status: "done",
|
|
20451
|
+
query: body.topic,
|
|
20452
|
+
resultCount: 0,
|
|
20453
|
+
result: result2
|
|
20454
|
+
});
|
|
20455
|
+
return c.json(result2);
|
|
20354
20456
|
}
|
|
20355
20457
|
let ranked;
|
|
20356
20458
|
if (!body.includeComments) {
|
|
@@ -20426,7 +20528,13 @@ redditApp.post("/trending", createApiKeyAuth(), async (c) => {
|
|
|
20426
20528
|
threadsScraped: body.includeComments ? ranked.length : 0,
|
|
20427
20529
|
candidatesFound: candidates.length,
|
|
20428
20530
|
partial: body.includeComments && ranked.length < candidates.length,
|
|
20429
|
-
searchQuery: serpQuery
|
|
20531
|
+
searchQuery: serpQuery,
|
|
20532
|
+
discoverySource,
|
|
20533
|
+
resultQuality: primaryDiscoveryDegraded ? "partial" : "complete",
|
|
20534
|
+
degradedResult: false,
|
|
20535
|
+
degradationReasons: primaryDiscoveryDegraded ? primaryDegradationReasons : [],
|
|
20536
|
+
retryRecommended: false,
|
|
20537
|
+
billingRefunded: false
|
|
20430
20538
|
};
|
|
20431
20539
|
await logRequestEvent({ userId: user.id, source: "reddit_trending", status: "done", query: body.topic, resultCount: ranked.length, result });
|
|
20432
20540
|
return c.json(result);
|
|
@@ -23886,6 +23994,24 @@ import { Hono as Hono21 } from "hono";
|
|
|
23886
23994
|
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
23887
23995
|
|
|
23888
23996
|
// src/mcp/memory-mcp-tool-executor.ts
|
|
23997
|
+
function folderInventory(result) {
|
|
23998
|
+
if (!Array.isArray(result.notes)) return [];
|
|
23999
|
+
const folders = /* @__PURE__ */ new Set();
|
|
24000
|
+
for (const note of result.notes) {
|
|
24001
|
+
if (!note || typeof note !== "object" || Array.isArray(note)) continue;
|
|
24002
|
+
const path5 = note.path;
|
|
24003
|
+
if (typeof path5 !== "string") continue;
|
|
24004
|
+
const segments = path5.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
24005
|
+
for (let depth = 1; depth < segments.length; depth += 1) {
|
|
24006
|
+
folders.add(segments.slice(0, depth).join("/"));
|
|
24007
|
+
}
|
|
24008
|
+
}
|
|
24009
|
+
return [...folders].sort((a, b) => a.localeCompare(b));
|
|
24010
|
+
}
|
|
24011
|
+
function enrichMemoryResult(toolName, result) {
|
|
24012
|
+
if (toolName !== "listTool" || result.ok !== true) return result;
|
|
24013
|
+
return { ...result, folders: folderInventory(result) };
|
|
24014
|
+
}
|
|
23889
24015
|
var MemoryMcpToolExecutor = class {
|
|
23890
24016
|
baseUrl;
|
|
23891
24017
|
apiKey;
|
|
@@ -23908,7 +24034,10 @@ var MemoryMcpToolExecutor = class {
|
|
|
23908
24034
|
const message = data?.error ?? `memory ${toolName} failed (HTTP ${res.status})`;
|
|
23909
24035
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
23910
24036
|
}
|
|
23911
|
-
const result =
|
|
24037
|
+
const result = enrichMemoryResult(
|
|
24038
|
+
toolName,
|
|
24039
|
+
data ?? { ok: false, error: `memory ${toolName} returned no result` }
|
|
24040
|
+
);
|
|
23912
24041
|
return {
|
|
23913
24042
|
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
23914
24043
|
structuredContent: result,
|
|
@@ -30749,6 +30878,24 @@ function safeFilename(requested, slug2) {
|
|
|
30749
30878
|
function escapedJsonForHtml(value) {
|
|
30750
30879
|
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
30751
30880
|
}
|
|
30881
|
+
function socialMeta(input) {
|
|
30882
|
+
const image = input.site.ogImage;
|
|
30883
|
+
const tags = [
|
|
30884
|
+
'<meta property="og:type" content="website">',
|
|
30885
|
+
`<meta property="og:title" content="${escapeHtml5(input.site.title)}">`,
|
|
30886
|
+
`<meta property="og:description" content="${escapeHtml5(input.deck || input.site.heroTitle)}">`,
|
|
30887
|
+
'<meta name="twitter:card" content="summary_large_image">',
|
|
30888
|
+
`<meta name="twitter:title" content="${escapeHtml5(input.site.title)}">`,
|
|
30889
|
+
`<meta name="twitter:description" content="${escapeHtml5(input.deck || input.site.heroTitle)}">`,
|
|
30890
|
+
`<meta property="og:image" content="${image ? escapeHtml5(image.url) : ""}">`,
|
|
30891
|
+
`<meta property="og:image:alt" content="${image ? escapeHtml5(image.alt) : ""}">`,
|
|
30892
|
+
`<meta property="og:image:width" content="${image?.width ?? ""}">`,
|
|
30893
|
+
`<meta property="og:image:height" content="${image?.height ?? ""}">`,
|
|
30894
|
+
`<meta name="twitter:image" content="${image ? escapeHtml5(image.url) : ""}">`,
|
|
30895
|
+
`<meta name="twitter:image:alt" content="${image ? escapeHtml5(image.alt) : ""}">`
|
|
30896
|
+
];
|
|
30897
|
+
return tags.join("\n ");
|
|
30898
|
+
}
|
|
30752
30899
|
function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
|
|
30753
30900
|
const sourceBytes = input.articles.reduce((total, article) => total + Buffer.byteLength(article.markdown), 0);
|
|
30754
30901
|
if (sourceBytes > 2e6) throw new Error("Editorial reading-room Markdown must be 2,000,000 bytes or fewer in total.");
|
|
@@ -30781,7 +30928,7 @@ function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
|
|
|
30781
30928
|
const generatedAt = now.toISOString();
|
|
30782
30929
|
const data = { ...input, generatedAt, articles };
|
|
30783
30930
|
const template = readAsset("index.html");
|
|
30784
|
-
const html = template.replace("<title>Editorial Reading Room</title>", `<title>${escapeHtml5(input.site.title)}</title>`).replace('content="A mobile-first editorial reading room."', `content="${escapeHtml5(input.deck || input.site.heroTitle)}"`).replace("/*__READING_ROOM_STYLES__*/", readAsset("styles.css")).replace("/*__READING_ROOM_DATA__*/", escapedJsonForHtml(data)).replace("/*__READING_ROOM_SCRIPT__*/", readAsset("app.js"));
|
|
30931
|
+
const html = template.replace("<title>Editorial Reading Room</title>", `<title>${escapeHtml5(input.site.title)}</title>`).replace('content="A mobile-first editorial reading room."', `content="${escapeHtml5(input.deck || input.site.heroTitle)}"`).replace("<!--__READING_ROOM_SOCIAL_META__-->", socialMeta(input)).replace("/*__READING_ROOM_STYLES__*/", readAsset("styles.css")).replace("/*__READING_ROOM_DATA__*/", escapedJsonForHtml(data)).replace("/*__READING_ROOM_SCRIPT__*/", readAsset("app.js"));
|
|
30785
30932
|
const bytes = Buffer.byteLength(html);
|
|
30786
30933
|
return {
|
|
30787
30934
|
html,
|
|
@@ -44403,4 +44550,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
44403
44550
|
export {
|
|
44404
44551
|
app
|
|
44405
44552
|
};
|
|
44406
|
-
//# sourceMappingURL=server-
|
|
44553
|
+
//# sourceMappingURL=server-IGIIEHXY.js.map
|