mcp-scraper 0.5.0 → 0.7.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 +675 -214
- 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 +322 -11
- 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 +166 -74
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/chunk-EGWJ74EX.js +7 -0
- package/dist/chunk-EGWJ74EX.js.map +1 -0
- package/dist/{chunk-APJO2XV5.js → chunk-HL33CGJF.js} +3 -3
- package/dist/{chunk-APJO2XV5.js.map → chunk-HL33CGJF.js.map} +1 -1
- package/dist/{chunk-AUCXKRRH.js → chunk-RMPPYKUV.js} +167 -75
- package/dist/chunk-RMPPYKUV.js.map +1 -0
- package/dist/{chunk-BL7BBSYF.js → chunk-RUGJE5EB.js} +2 -2
- package/dist/{chunk-J4T5OSCF.js → chunk-YGRZU7IR.js} +322 -11
- package/dist/chunk-YGRZU7IR.js.map +1 -0
- package/dist/index.cjs +166 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{server-Z4MEISH5.js → server-JNY4XPZE.js} +138 -81
- package/dist/server-JNY4XPZE.js.map +1 -0
- package/dist/{site-extract-repository-U476J44K.js → site-extract-repository-NVSZH35Y.js} +3 -3
- package/dist/{worker-KJZ3ZN2N.js → worker-JQTS437L.js} +4 -4
- package/dist/worker-JQTS437L.js.map +1 -0
- package/package.json +2 -2
- package/dist/chunk-3RTPEQJC.js +0 -7
- package/dist/chunk-3RTPEQJC.js.map +0 -1
- package/dist/chunk-AUCXKRRH.js.map +0 -1
- package/dist/chunk-J4T5OSCF.js.map +0 -1
- package/dist/server-Z4MEISH5.js.map +0 -1
- package/dist/worker-KJZ3ZN2N.js.map +0 -1
- package/docs/spec-browser-routing.md +0 -108
- package/docs/spec-kernel-computer-controls.md +0 -166
- package/docs/spec-mcp-tools.md +0 -146
- package/docs/spec-server-instructions.md +0 -94
- package/docs/specs/agent-ready-seo-packet-spec.md +0 -237
- package/docs/specs/audit-visual-demo.md +0 -309
- package/docs/specs/cli-agent-wiring-spec.md +0 -206
- package/docs/specs/local-competitive-audit-spec.md +0 -311
- package/docs/specs/scheduled-workflows-api-spec.md +0 -304
- package/docs/specs/seo-cli-growth-roadmap-spec.md +0 -181
- package/docs/specs/seo-workflow-runner-and-reports-spec.md +0 -241
- /package/dist/{chunk-BL7BBSYF.js.map → chunk-RUGJE5EB.js.map} +0 -0
- /package/dist/{site-extract-repository-U476J44K.js.map → site-extract-repository-NVSZH35Y.js.map} +0 -0
package/dist/bin/api-server.cjs
CHANGED
|
@@ -6372,8 +6372,8 @@ async function downloadAsset(url, destDir, filename) {
|
|
|
6372
6372
|
}
|
|
6373
6373
|
const writer = (0, import_node_fs.createWriteStream)(dest);
|
|
6374
6374
|
await (0, import_promises2.pipeline)(import_node_stream.Readable.fromWeb(res.body), writer);
|
|
6375
|
-
const { statSync:
|
|
6376
|
-
const sizeBytes =
|
|
6375
|
+
const { statSync: statSync2 } = await import("fs");
|
|
6376
|
+
const sizeBytes = statSync2(dest).size;
|
|
6377
6377
|
return { savedPath: dest, sizeBytes, mimeType };
|
|
6378
6378
|
}
|
|
6379
6379
|
async function harvestPageMedia(html, pageUrl, options = {}) {
|
|
@@ -7992,8 +7992,8 @@ var init_rates = __esm({
|
|
|
7992
7992
|
"use strict";
|
|
7993
7993
|
MC_COSTS = {
|
|
7994
7994
|
serp: 100,
|
|
7995
|
-
paa:
|
|
7996
|
-
paa_base:
|
|
7995
|
+
paa: 300,
|
|
7996
|
+
paa_base: 5500,
|
|
7997
7997
|
page_scrape: 100,
|
|
7998
7998
|
url_map: 500,
|
|
7999
7999
|
yt_channel: 200,
|
|
@@ -10648,8 +10648,8 @@ var init_blob_store = __esm({
|
|
|
10648
10648
|
async get(key) {
|
|
10649
10649
|
const path6 = (0, import_node_path2.join)(this.baseDir, "blobs", key);
|
|
10650
10650
|
try {
|
|
10651
|
-
const { readFileSync:
|
|
10652
|
-
return
|
|
10651
|
+
const { readFileSync: readFileSync6 } = await import("fs");
|
|
10652
|
+
return readFileSync6(path6);
|
|
10653
10653
|
} catch {
|
|
10654
10654
|
return null;
|
|
10655
10655
|
}
|
|
@@ -15788,6 +15788,12 @@ var init_facebook_ad_routes = __esm({
|
|
|
15788
15788
|
}
|
|
15789
15789
|
}
|
|
15790
15790
|
const results = [...advertiserMap.values()].sort((a, b) => b.adCount - a.adCount).slice(0, maxResults).map((a) => ({ name: a.pageName, pageName: a.pageName, libraryId: a.sampleLibraryId, sampleLibraryId: a.sampleLibraryId, adCount: a.adCount }));
|
|
15791
|
+
if (results.length === 0) {
|
|
15792
|
+
await creditMc(fbUser.id, MC_COSTS.fb_search, LedgerOperation.FB_SEARCH_REFUND, "empty result");
|
|
15793
|
+
searchRefunded = true;
|
|
15794
|
+
await logRequestEvent({ userId: fbUser.id, source: "facebook_search", status: "failed", query: body.query.trim(), error: "empty result refunded" });
|
|
15795
|
+
return c.json({ error: "no advertisers found (refunded)" }, 503);
|
|
15796
|
+
}
|
|
15791
15797
|
const searchResult = { query: body.query.trim(), searchUrl, results };
|
|
15792
15798
|
await logRequestEvent({ userId: fbUser.id, source: "facebook_search", status: "done", query: body.query.trim(), resultCount: results.length, result: searchResult });
|
|
15793
15799
|
return c.json(searchResult);
|
|
@@ -16600,20 +16606,15 @@ async function resolveInstagramLaunch(body) {
|
|
|
16600
16606
|
}
|
|
16601
16607
|
};
|
|
16602
16608
|
}
|
|
16603
|
-
function outputBaseDir() {
|
|
16604
|
-
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || (0, import_node_path7.join)((0, import_node_os5.homedir)(), "Downloads", "mcp-scraper");
|
|
16605
|
-
}
|
|
16606
16609
|
function safeFilePart(input) {
|
|
16607
16610
|
return input.replace(/^https?:\/\//, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "instagram";
|
|
16608
16611
|
}
|
|
16609
|
-
function
|
|
16612
|
+
function blobKeyPrefix(shortcode, sourceUrl) {
|
|
16610
16613
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
16611
16614
|
const slug = shortcode ? `instagram-${shortcode}` : safeFilePart(sourceUrl);
|
|
16612
|
-
|
|
16613
|
-
(0, import_node_fs5.mkdirSync)(dir, { recursive: true });
|
|
16614
|
-
return dir;
|
|
16615
|
+
return `instagram/${stamp}-${slug}`;
|
|
16615
16616
|
}
|
|
16616
|
-
async function
|
|
16617
|
+
async function fetchMediaBytes(url, referer) {
|
|
16617
16618
|
const res = await fetch(url, {
|
|
16618
16619
|
headers: {
|
|
16619
16620
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
|
|
@@ -16623,12 +16624,8 @@ async function downloadToFile(url, destPath, referer) {
|
|
|
16623
16624
|
});
|
|
16624
16625
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
16625
16626
|
if (!res.body) throw new Error("Empty response body");
|
|
16626
|
-
|
|
16627
|
-
return {
|
|
16628
|
-
savedPath: destPath,
|
|
16629
|
-
sizeBytes: (0, import_node_fs5.statSync)(destPath).size,
|
|
16630
|
-
mimeType: res.headers.get("content-type")?.split(";")[0]?.trim() ?? null
|
|
16631
|
-
};
|
|
16627
|
+
const bytes = Buffer.from(await res.arrayBuffer());
|
|
16628
|
+
return { bytes, mimeType: res.headers.get("content-type")?.split(";")[0]?.trim() ?? null };
|
|
16632
16629
|
}
|
|
16633
16630
|
function extFromMime(mimeType, fallback) {
|
|
16634
16631
|
const map = {
|
|
@@ -16661,7 +16658,7 @@ function trackFilename(track, index, shortcode) {
|
|
|
16661
16658
|
const bitrate = track.bitrate ? `-${track.bitrate}` : "";
|
|
16662
16659
|
return `${label}-${type}-${index}${bitrate}.mp4`;
|
|
16663
16660
|
}
|
|
16664
|
-
var import_hono7, import_zod18, import_node_fs5, import_node_os5, import_node_path7,
|
|
16661
|
+
var import_hono7, import_zod18, import_node_fs5, import_node_os5, import_node_path7, import_node_child_process2, InstagramProfileContentBodySchema, InstagramMediaTypeSchema, InstagramMediaDownloadBodySchema, instagramApp;
|
|
16665
16662
|
var init_instagram_routes = __esm({
|
|
16666
16663
|
"src/api/instagram-routes.ts"() {
|
|
16667
16664
|
"use strict";
|
|
@@ -16670,8 +16667,6 @@ var init_instagram_routes = __esm({
|
|
|
16670
16667
|
import_node_fs5 = require("fs");
|
|
16671
16668
|
import_node_os5 = require("os");
|
|
16672
16669
|
import_node_path7 = require("path");
|
|
16673
|
-
import_node_stream2 = require("stream");
|
|
16674
|
-
import_promises4 = require("stream/promises");
|
|
16675
16670
|
import_node_child_process2 = require("child_process");
|
|
16676
16671
|
init_browser_service_env();
|
|
16677
16672
|
init_BrowserDriver();
|
|
@@ -16680,6 +16675,7 @@ var init_instagram_routes = __esm({
|
|
|
16680
16675
|
init_db();
|
|
16681
16676
|
init_rates();
|
|
16682
16677
|
init_concurrency_gates();
|
|
16678
|
+
init_blob_store();
|
|
16683
16679
|
init_InstagramContentExtractor();
|
|
16684
16680
|
init_media_transcription();
|
|
16685
16681
|
InstagramProfileContentBodySchema = import_zod18.z.object({
|
|
@@ -16794,55 +16790,65 @@ var init_instagram_routes = __esm({
|
|
|
16794
16790
|
const mediaTypes = new Set(body.mediaTypes);
|
|
16795
16791
|
const downloads = [];
|
|
16796
16792
|
const warnings = [];
|
|
16797
|
-
let outputDir = null;
|
|
16798
16793
|
if (body.downloadMedia) {
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
|
|
16804
|
-
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
const
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
|
|
16815
|
-
const
|
|
16816
|
-
|
|
16794
|
+
let muxWorkDir = null;
|
|
16795
|
+
try {
|
|
16796
|
+
const store = getBlobStore();
|
|
16797
|
+
const prefix = blobKeyPrefix(extraction.shortcode, sourceUrl.href);
|
|
16798
|
+
const textContent = [
|
|
16799
|
+
`URL: ${extraction.pageUrl}`,
|
|
16800
|
+
extraction.caption ? `Caption: ${extraction.caption}` : "",
|
|
16801
|
+
"",
|
|
16802
|
+
extraction.bodyText
|
|
16803
|
+
].filter(Boolean).join("\n");
|
|
16804
|
+
const storedText = await store.put(`${prefix}/text.txt`, textContent, "text/plain");
|
|
16805
|
+
downloads.push({ kind: "text", url: null, savedPath: storedText.url, sizeBytes: storedText.bytes, mimeType: "text/plain", error: null });
|
|
16806
|
+
if (mediaTypes.has("image") && extraction.imageUrl) {
|
|
16807
|
+
try {
|
|
16808
|
+
const { bytes, mimeType } = await fetchMediaBytes(extraction.imageUrl, extraction.pageUrl);
|
|
16809
|
+
const ext = extFromMime(mimeType, "jpg");
|
|
16810
|
+
const stored = await store.put(`${prefix}/image.${ext}`, bytes, mimeType ?? "application/octet-stream");
|
|
16811
|
+
downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: stored.url, sizeBytes: stored.bytes, mimeType, error: null });
|
|
16812
|
+
} catch (err) {
|
|
16813
|
+
downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: null, sizeBytes: null, mimeType: null, error: err instanceof Error ? err.message : String(err) });
|
|
16817
16814
|
}
|
|
16818
|
-
downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: finalPath, sizeBytes: (0, import_node_fs5.statSync)(finalPath).size, mimeType: downloaded.mimeType, error: null });
|
|
16819
|
-
} catch (err) {
|
|
16820
|
-
downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: null, sizeBytes: null, mimeType: null, error: err instanceof Error ? err.message : String(err) });
|
|
16821
16815
|
}
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
16830
|
-
|
|
16831
|
-
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
|
|
16835
|
-
|
|
16816
|
+
const tracksToDownload = body.downloadAllTracks ? extraction.tracks : [extraction.selectedVideoTrack, extraction.selectedAudioTrack].filter((track) => Boolean(track));
|
|
16817
|
+
const muxEligible = Boolean(body.mux && mediaTypes.has("video") && mediaTypes.has("audio") && extraction.selectedVideoTrack && extraction.selectedAudioTrack);
|
|
16818
|
+
const muxInputs = /* @__PURE__ */ new Map();
|
|
16819
|
+
for (const [index, track] of tracksToDownload.entries()) {
|
|
16820
|
+
if (track.streamType === "video" && !mediaTypes.has("video")) continue;
|
|
16821
|
+
if (track.streamType === "audio" && !mediaTypes.has("audio")) continue;
|
|
16822
|
+
const kind = track.streamType === "audio" ? "audio" : "video";
|
|
16823
|
+
try {
|
|
16824
|
+
const { bytes, mimeType } = await fetchMediaBytes(track.url, extraction.pageUrl);
|
|
16825
|
+
const stored = await store.put(`${prefix}/${trackFilename(track, index, extraction.shortcode)}`, bytes, mimeType ?? "video/mp4");
|
|
16826
|
+
downloads.push({ kind, url: track.url, savedPath: stored.url, sizeBytes: stored.bytes, mimeType, error: null });
|
|
16827
|
+
const isMuxInput = muxEligible && (track.url === extraction.selectedVideoTrack.url || track.url === extraction.selectedAudioTrack.url);
|
|
16828
|
+
if (isMuxInput) {
|
|
16829
|
+
if (!muxWorkDir) muxWorkDir = (0, import_node_fs5.mkdtempSync)((0, import_node_path7.join)((0, import_node_os5.tmpdir)(), "ig-mux-"));
|
|
16830
|
+
const localPath = (0, import_node_path7.join)(muxWorkDir, trackFilename(track, index, extraction.shortcode));
|
|
16831
|
+
(0, import_node_fs5.writeFileSync)(localPath, bytes);
|
|
16832
|
+
muxInputs.set(track.url, localPath);
|
|
16833
|
+
}
|
|
16834
|
+
} catch (err) {
|
|
16835
|
+
downloads.push({ kind, url: track.url, savedPath: null, sizeBytes: null, mimeType: null, error: err instanceof Error ? err.message : String(err) });
|
|
16836
|
+
}
|
|
16836
16837
|
}
|
|
16837
|
-
|
|
16838
|
-
|
|
16839
|
-
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
-
|
|
16843
|
-
|
|
16844
|
-
|
|
16838
|
+
if (muxEligible && muxWorkDir && muxInputs.has(extraction.selectedVideoTrack.url) && muxInputs.has(extraction.selectedAudioTrack.url)) {
|
|
16839
|
+
const outPath = (0, import_node_path7.join)(muxWorkDir, "muxed.mp4");
|
|
16840
|
+
const muxed = await runFfmpegMux(muxInputs.get(extraction.selectedVideoTrack.url), muxInputs.get(extraction.selectedAudioTrack.url), outPath);
|
|
16841
|
+
if (muxed.ok) {
|
|
16842
|
+
const stored = await store.put(`${prefix}/muxed.mp4`, (0, import_node_fs5.readFileSync)(outPath), "video/mp4");
|
|
16843
|
+
downloads.push({ kind: "muxed_video", url: null, savedPath: stored.url, sizeBytes: stored.bytes, mimeType: "video/mp4", error: null });
|
|
16844
|
+
} else {
|
|
16845
|
+
warnings.push(`Mux skipped/failed: ${muxed.error}`);
|
|
16846
|
+
}
|
|
16845
16847
|
}
|
|
16848
|
+
} catch (err) {
|
|
16849
|
+
warnings.push(`Media download unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
16850
|
+
} finally {
|
|
16851
|
+
if (muxWorkDir) (0, import_node_fs5.rmSync)(muxWorkDir, { recursive: true, force: true });
|
|
16846
16852
|
}
|
|
16847
16853
|
}
|
|
16848
16854
|
let transcript = null;
|
|
@@ -16865,7 +16871,7 @@ var init_instagram_routes = __esm({
|
|
|
16865
16871
|
const result = {
|
|
16866
16872
|
...extraction,
|
|
16867
16873
|
browser: launch.browser,
|
|
16868
|
-
outputDir,
|
|
16874
|
+
outputDir: null,
|
|
16869
16875
|
downloads,
|
|
16870
16876
|
warnings,
|
|
16871
16877
|
transcript
|
|
@@ -17147,9 +17153,6 @@ async function memoryCall(toolName, args, userMemoryKey) {
|
|
|
17147
17153
|
return { ok: false, error: err?.message ?? "memory call failed" };
|
|
17148
17154
|
}
|
|
17149
17155
|
}
|
|
17150
|
-
function personalVault(user) {
|
|
17151
|
-
return `mcp-${user.id}`;
|
|
17152
|
-
}
|
|
17153
17156
|
function memoryIdentity(user) {
|
|
17154
17157
|
return user.email;
|
|
17155
17158
|
}
|
|
@@ -19067,12 +19070,12 @@ function reportTitle(full) {
|
|
|
19067
19070
|
const title = full.split("\n").find((line) => line.startsWith("# "));
|
|
19068
19071
|
return title?.replace(/^#\s+/, "").trim() || "MCP Scraper Report";
|
|
19069
19072
|
}
|
|
19070
|
-
function
|
|
19073
|
+
function outputBaseDir() {
|
|
19071
19074
|
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || (0, import_node_path8.join)((0, import_node_os6.homedir)(), "Downloads", "mcp-scraper");
|
|
19072
19075
|
}
|
|
19073
19076
|
function saveFullReport(full) {
|
|
19074
19077
|
if (!reportSavingEnabled || process.env.MCP_SCRAPER_SAVE_REPORTS === "false") return null;
|
|
19075
|
-
const outDir =
|
|
19078
|
+
const outDir = outputBaseDir();
|
|
19076
19079
|
try {
|
|
19077
19080
|
(0, import_node_fs6.mkdirSync)(outDir, { recursive: true });
|
|
19078
19081
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -19090,7 +19093,7 @@ function saveBulkSite(siteUrl, pages, seo, imageAudit) {
|
|
|
19090
19093
|
if (!reportSavingActive()) return null;
|
|
19091
19094
|
try {
|
|
19092
19095
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
19093
|
-
const dir = (0, import_node_path8.join)(
|
|
19096
|
+
const dir = (0, import_node_path8.join)(outputBaseDir(), `extract-${slugifyReportName(siteUrl)}-${stamp}`);
|
|
19094
19097
|
const pagesDir = (0, import_node_path8.join)(dir, "pages");
|
|
19095
19098
|
(0, import_node_fs6.mkdirSync)(pagesDir, { recursive: true });
|
|
19096
19099
|
const indexRows = pages.map((p, i) => {
|
|
@@ -19183,7 +19186,7 @@ ${renderImageSection(imageAudit)}` : ""), "utf8");
|
|
|
19183
19186
|
function saveUrlInventory(siteUrl, urls) {
|
|
19184
19187
|
if (!reportSavingActive()) return null;
|
|
19185
19188
|
try {
|
|
19186
|
-
const outDir =
|
|
19189
|
+
const outDir = outputBaseDir();
|
|
19187
19190
|
(0, import_node_fs6.mkdirSync)(outDir, { recursive: true });
|
|
19188
19191
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
19189
19192
|
const file = (0, import_node_path8.join)(outDir, `${stamp}-urlmap-${slugifyReportName(siteUrl.replace(/^https?:\/\//, ""))}.csv`);
|
|
@@ -19198,7 +19201,7 @@ function saveUrlInventory(siteUrl, urls) {
|
|
|
19198
19201
|
function persistScreenshotLocally(base64, url) {
|
|
19199
19202
|
if (!reportSavingEnabled || process.env.MCP_SCRAPER_SAVE_REPORTS === "false") return null;
|
|
19200
19203
|
try {
|
|
19201
|
-
const dir = (0, import_node_path8.join)(
|
|
19204
|
+
const dir = (0, import_node_path8.join)(outputBaseDir(), "screenshots");
|
|
19202
19205
|
(0, import_node_fs6.mkdirSync)(dir, { recursive: true });
|
|
19203
19206
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
19204
19207
|
const slug = url.replace(/^https?:\/\//, "").replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").slice(0, 60);
|
|
@@ -21478,7 +21481,7 @@ function localLocationFileAllowed() {
|
|
|
21478
21481
|
async function existingPath(value) {
|
|
21479
21482
|
const trimmed = value?.trim();
|
|
21480
21483
|
if (!trimmed) return null;
|
|
21481
|
-
await (0,
|
|
21484
|
+
await (0, import_promises4.access)(trimmed);
|
|
21482
21485
|
return trimmed;
|
|
21483
21486
|
}
|
|
21484
21487
|
async function resolveUsZipsPath(requestedPath) {
|
|
@@ -21496,7 +21499,7 @@ async function loadZipGroups(stateAbbr, requestedPath, warnings) {
|
|
|
21496
21499
|
}
|
|
21497
21500
|
const path6 = await resolveUsZipsPath(requestedPath);
|
|
21498
21501
|
if (!path6) return { path: null, groups: /* @__PURE__ */ new Map() };
|
|
21499
|
-
const records = csvRecords(await (0,
|
|
21502
|
+
const records = csvRecords(await (0, import_promises4.readFile)(path6, "utf8"));
|
|
21500
21503
|
const groups = /* @__PURE__ */ new Map();
|
|
21501
21504
|
for (const record of records) {
|
|
21502
21505
|
const state = (record.state_abbr ?? record.state ?? "").trim().toUpperCase();
|
|
@@ -21547,11 +21550,11 @@ async function resolveDirectoryMarkets(options) {
|
|
|
21547
21550
|
}
|
|
21548
21551
|
return { markets, censusSourceUrl: sourceUrl, usZipsSourcePath: zipData.path, warnings };
|
|
21549
21552
|
}
|
|
21550
|
-
var
|
|
21553
|
+
var import_promises4, POPULATION_YEARS, STATE_META, STATE_BY_NAME;
|
|
21551
21554
|
var init_location_db = __esm({
|
|
21552
21555
|
"src/directory/location-db.ts"() {
|
|
21553
21556
|
"use strict";
|
|
21554
|
-
|
|
21557
|
+
import_promises4 = require("fs/promises");
|
|
21555
21558
|
init_csv();
|
|
21556
21559
|
POPULATION_YEARS = [2020, 2021, 2022, 2023, 2024, 2025];
|
|
21557
21560
|
STATE_META = {
|
|
@@ -21767,8 +21770,8 @@ function csvRowsFor(result) {
|
|
|
21767
21770
|
return rows;
|
|
21768
21771
|
}
|
|
21769
21772
|
async function saveDirectoryCsv(result) {
|
|
21770
|
-
const outDir = (0, import_node_path9.join)(
|
|
21771
|
-
await (0,
|
|
21773
|
+
const outDir = (0, import_node_path9.join)(outputBaseDir(), "directory-workflows");
|
|
21774
|
+
await (0, import_promises5.mkdir)(outDir, { recursive: true });
|
|
21772
21775
|
const stamp = result.extractedAt.replace(/[:.]/g, "-");
|
|
21773
21776
|
const slug = `${result.state}-${result.query}`.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
21774
21777
|
const path6 = (0, import_node_path9.join)(outDir, `${stamp}-${slug}-directory-workflow.csv`);
|
|
@@ -21803,7 +21806,7 @@ async function saveDirectoryCsv(result) {
|
|
|
21803
21806
|
"extracted_at",
|
|
21804
21807
|
"duration_ms"
|
|
21805
21808
|
];
|
|
21806
|
-
await (0,
|
|
21809
|
+
await (0, import_promises5.writeFile)(path6, rowsToCsv(headers, csvRowsFor(result)), "utf8");
|
|
21807
21810
|
return path6;
|
|
21808
21811
|
}
|
|
21809
21812
|
async function runDirectoryWorkflowFromPlan(options, plan) {
|
|
@@ -21829,11 +21832,11 @@ async function runDirectoryWorkflowFromPlan(options, plan) {
|
|
|
21829
21832
|
const csvPath = options.saveCsv ? await saveDirectoryCsv(base) : null;
|
|
21830
21833
|
return { ...base, csvPath };
|
|
21831
21834
|
}
|
|
21832
|
-
var
|
|
21835
|
+
var import_promises5, import_node_path9, import_zod24, DirectoryWorkflowOptionsSchema;
|
|
21833
21836
|
var init_directory_workflow = __esm({
|
|
21834
21837
|
"src/directory/directory-workflow.ts"() {
|
|
21835
21838
|
"use strict";
|
|
21836
|
-
|
|
21839
|
+
import_promises5 = require("fs/promises");
|
|
21837
21840
|
import_node_path9 = require("path");
|
|
21838
21841
|
import_zod24 = require("zod");
|
|
21839
21842
|
init_mcp_response_formatter();
|
|
@@ -22001,7 +22004,7 @@ async function readIndex(baseDir) {
|
|
|
22001
22004
|
const path6 = indexPath(baseDir);
|
|
22002
22005
|
if (!(0, import_node_fs7.existsSync)(path6)) return { runs: [] };
|
|
22003
22006
|
try {
|
|
22004
|
-
return JSON.parse(await (0,
|
|
22007
|
+
return JSON.parse(await (0, import_promises6.readFile)(path6, "utf8"));
|
|
22005
22008
|
} catch {
|
|
22006
22009
|
return { runs: [] };
|
|
22007
22010
|
}
|
|
@@ -22021,14 +22024,14 @@ async function updateWorkflowIndex(manifest, manifestPath, baseDir) {
|
|
|
22021
22024
|
summary: `${manifest.title} (${manifest.status})`
|
|
22022
22025
|
};
|
|
22023
22026
|
index.runs = [entry, ...index.runs.filter((r) => r.runId !== manifest.runId)].slice(0, 200);
|
|
22024
|
-
await (0,
|
|
22025
|
-
await (0,
|
|
22027
|
+
await (0, import_promises6.mkdir)((0, import_node_path10.dirname)(path6), { recursive: true });
|
|
22028
|
+
await (0, import_promises6.writeFile)(path6, JSON.stringify(index, null, 2), "utf8");
|
|
22026
22029
|
}
|
|
22027
|
-
var
|
|
22030
|
+
var import_promises6, import_node_fs7, import_node_os7, import_node_path10, import_node_child_process3, ArtifactWriter;
|
|
22028
22031
|
var init_artifact_writer = __esm({
|
|
22029
22032
|
"src/workflows/artifact-writer.ts"() {
|
|
22030
22033
|
"use strict";
|
|
22031
|
-
|
|
22034
|
+
import_promises6 = require("fs/promises");
|
|
22032
22035
|
import_node_fs7 = require("fs");
|
|
22033
22036
|
import_node_os7 = require("os");
|
|
22034
22037
|
import_node_path10 = require("path");
|
|
@@ -22060,31 +22063,31 @@ var init_artifact_writer = __esm({
|
|
|
22060
22063
|
const nameSource = String(input.keyword ?? input.query ?? input.domain ?? input.state ?? workflowId);
|
|
22061
22064
|
const baseDir = workflowOutputBaseDir(outputDir);
|
|
22062
22065
|
const runDir = (0, import_node_path10.join)(baseDir, "workflows", workflowId, `${timestamp()}-${safeSlug(nameSource)}-${safeSlug(runId).slice(0, 20)}`);
|
|
22063
|
-
await (0,
|
|
22066
|
+
await (0, import_promises6.mkdir)(runDir, { recursive: true });
|
|
22064
22067
|
return new _ArtifactWriter(workflowId, title, runId, baseDir, runDir, startedAt, input);
|
|
22065
22068
|
}
|
|
22066
22069
|
async remember(kind, label, path6, rows) {
|
|
22067
|
-
const size = await (0,
|
|
22070
|
+
const size = await (0, import_promises6.stat)(path6).then((s) => s.size).catch(() => void 0);
|
|
22068
22071
|
this.artifacts.push({ kind, label, path: path6, bytes: size, rows });
|
|
22069
22072
|
await postToMemoryLibrary({ title: `${this.title} ${label}`, content: `artifact: ${path6}`, source: `mcp-scraper-workflow:${this.workflowId}:${this.runId}` });
|
|
22070
22073
|
return path6;
|
|
22071
22074
|
}
|
|
22072
22075
|
async writeJson(label, relativePath, data) {
|
|
22073
22076
|
const path6 = (0, import_node_path10.join)(this.runDir, relativePath);
|
|
22074
|
-
await (0,
|
|
22075
|
-
await (0,
|
|
22077
|
+
await (0, import_promises6.mkdir)((0, import_node_path10.dirname)(path6), { recursive: true });
|
|
22078
|
+
await (0, import_promises6.writeFile)(path6, JSON.stringify(data, null, 2), "utf8");
|
|
22076
22079
|
return this.remember("json", label, path6);
|
|
22077
22080
|
}
|
|
22078
22081
|
async writeText(label, relativePath, text, kind = "markdown") {
|
|
22079
22082
|
const path6 = (0, import_node_path10.join)(this.runDir, relativePath);
|
|
22080
|
-
await (0,
|
|
22081
|
-
await (0,
|
|
22083
|
+
await (0, import_promises6.mkdir)((0, import_node_path10.dirname)(path6), { recursive: true });
|
|
22084
|
+
await (0, import_promises6.writeFile)(path6, text, "utf8");
|
|
22082
22085
|
return this.remember(kind, label, path6);
|
|
22083
22086
|
}
|
|
22084
22087
|
async writeCsv(label, relativePath, headers, rows) {
|
|
22085
22088
|
const path6 = (0, import_node_path10.join)(this.runDir, relativePath);
|
|
22086
|
-
await (0,
|
|
22087
|
-
await (0,
|
|
22089
|
+
await (0, import_promises6.mkdir)((0, import_node_path10.dirname)(path6), { recursive: true });
|
|
22090
|
+
await (0, import_promises6.writeFile)(path6, rowsToCsv(headers, rows), "utf8");
|
|
22088
22091
|
return this.remember("csv", label, path6, rows.length);
|
|
22089
22092
|
}
|
|
22090
22093
|
async writeHtml(label, relativePath, html) {
|
|
@@ -22105,7 +22108,7 @@ var init_artifact_writer = __esm({
|
|
|
22105
22108
|
counts
|
|
22106
22109
|
};
|
|
22107
22110
|
const path6 = (0, import_node_path10.join)(this.runDir, "manifest.json");
|
|
22108
|
-
await (0,
|
|
22111
|
+
await (0, import_promises6.writeFile)(path6, JSON.stringify(manifest, null, 2), "utf8");
|
|
22109
22112
|
await updateWorkflowIndex(manifest, path6, this.baseDir);
|
|
22110
22113
|
return path6;
|
|
22111
22114
|
}
|
|
@@ -23831,7 +23834,7 @@ async function runWorkflowStep(id, rawInput, opts) {
|
|
|
23831
23834
|
const writtenArtifacts = await Promise.all(
|
|
23832
23835
|
artifacts.artifacts.map(async (artifact) => ({
|
|
23833
23836
|
...artifact,
|
|
23834
|
-
content: await (0,
|
|
23837
|
+
content: await (0, import_promises7.readFile)(artifact.path, "utf8").catch(() => "")
|
|
23835
23838
|
}))
|
|
23836
23839
|
);
|
|
23837
23840
|
return {
|
|
@@ -23850,11 +23853,11 @@ async function runWorkflowStep(id, rawInput, opts) {
|
|
|
23850
23853
|
artifacts: writtenArtifacts
|
|
23851
23854
|
};
|
|
23852
23855
|
}
|
|
23853
|
-
var
|
|
23856
|
+
var import_promises7, import_zod30, DEFINITIONS;
|
|
23854
23857
|
var init_registry2 = __esm({
|
|
23855
23858
|
"src/workflows/registry.ts"() {
|
|
23856
23859
|
"use strict";
|
|
23857
|
-
|
|
23860
|
+
import_promises7 = require("fs/promises");
|
|
23858
23861
|
import_zod30 = require("zod");
|
|
23859
23862
|
init_artifact_writer();
|
|
23860
23863
|
init_http_client2();
|
|
@@ -23925,7 +23928,7 @@ async function readManifestFromSummary(summary) {
|
|
|
23925
23928
|
if (!summary.reportPath) return null;
|
|
23926
23929
|
const manifestPath = summary.reportPath.replace(/report\.html$/, "manifest.json");
|
|
23927
23930
|
try {
|
|
23928
|
-
return JSON.parse(await (0,
|
|
23931
|
+
return JSON.parse(await (0, import_promises8.readFile)(manifestPath, "utf8"));
|
|
23929
23932
|
} catch {
|
|
23930
23933
|
return null;
|
|
23931
23934
|
}
|
|
@@ -24140,12 +24143,12 @@ async function dispatchDueWorkflowSchedules(apiUrl, limit = 3) {
|
|
|
24140
24143
|
}
|
|
24141
24144
|
return { dispatched: results.length, results };
|
|
24142
24145
|
}
|
|
24143
|
-
var import_node_crypto8,
|
|
24146
|
+
var import_node_crypto8, import_promises8, import_hono14, import_zod31, workflowApp, WorkflowInputSchema, WorkflowIdSchema, CadenceSchema, ScheduleStatusSchema, RunBodySchema, ScheduleCreateSchema, SchedulePatchSchema, TERMINAL_RUN_STATUSES;
|
|
24144
24147
|
var init_workflow_routes = __esm({
|
|
24145
24148
|
"src/api/workflow-routes.ts"() {
|
|
24146
24149
|
"use strict";
|
|
24147
24150
|
import_node_crypto8 = require("crypto");
|
|
24148
|
-
|
|
24151
|
+
import_promises8 = require("fs/promises");
|
|
24149
24152
|
import_hono14 = require("hono");
|
|
24150
24153
|
import_zod31 = require("zod");
|
|
24151
24154
|
init_artifact_writer();
|
|
@@ -24315,7 +24318,7 @@ var init_workflow_routes = __esm({
|
|
|
24315
24318
|
return new Response(artifact.content, { headers });
|
|
24316
24319
|
}
|
|
24317
24320
|
try {
|
|
24318
|
-
const content = await (0,
|
|
24321
|
+
const content = await (0, import_promises8.readFile)(artifact.path);
|
|
24319
24322
|
return new Response(content, { headers });
|
|
24320
24323
|
} catch {
|
|
24321
24324
|
return c.json({ error: "Artifact file is no longer available" }, 410);
|
|
@@ -25254,13 +25257,41 @@ var init_PAAExtractor = __esm({
|
|
|
25254
25257
|
}
|
|
25255
25258
|
return parts.join(" ").replace(/\s+/g, " ").trim();
|
|
25256
25259
|
}
|
|
25257
|
-
return Array.from(document.querySelectorAll(selectors.item)).map((pair) =>
|
|
25258
|
-
|
|
25259
|
-
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
25263
|
-
|
|
25260
|
+
return Array.from(document.querySelectorAll(selectors.item)).map((pair) => {
|
|
25261
|
+
let sourceTitle = pair.querySelector(selectors.sourceTitle)?.innerText?.trim() || void 0;
|
|
25262
|
+
let sourceSite = pair.querySelector(selectors.sourceSite)?.innerText?.trim() || void 0;
|
|
25263
|
+
let sourceCite = pair.querySelector(selectors.sourceCite)?.innerText?.trim() || void 0;
|
|
25264
|
+
if (!sourceCite) {
|
|
25265
|
+
const seenHrefs = /* @__PURE__ */ new Set();
|
|
25266
|
+
const anchors = [];
|
|
25267
|
+
for (const a of Array.from(pair.querySelectorAll("a[href]"))) {
|
|
25268
|
+
const href = a.href;
|
|
25269
|
+
if (!/^https?:\/\//.test(href) || seenHrefs.has(href)) continue;
|
|
25270
|
+
let host = "";
|
|
25271
|
+
try {
|
|
25272
|
+
host = new URL(href).hostname;
|
|
25273
|
+
} catch {
|
|
25274
|
+
continue;
|
|
25275
|
+
}
|
|
25276
|
+
if (/(^|\.)google(usercontent)?\.[a-z.]+$/.test(host)) continue;
|
|
25277
|
+
seenHrefs.add(href);
|
|
25278
|
+
anchors.push({ text: (a.textContent || "").trim(), href, host });
|
|
25279
|
+
}
|
|
25280
|
+
const primary = anchors.find((x) => x.text.length > 2) ?? anchors[0];
|
|
25281
|
+
if (primary) {
|
|
25282
|
+
sourceTitle = sourceTitle || primary.text || void 0;
|
|
25283
|
+
sourceSite = sourceSite || primary.host.replace(/^www\./, "");
|
|
25284
|
+
sourceCite = primary.href;
|
|
25285
|
+
}
|
|
25286
|
+
}
|
|
25287
|
+
return {
|
|
25288
|
+
question: pair.getAttribute(selectors.itemDataQ) || pair.getAttribute(selectors.itemDataInitQ) || pair.querySelector(selectors.itemQuestionEl)?.innerText?.trim() || "",
|
|
25289
|
+
answer: cleanText(pair.querySelector(selectors.answerContainer)) || void 0,
|
|
25290
|
+
sourceTitle,
|
|
25291
|
+
sourceSite,
|
|
25292
|
+
sourceCite
|
|
25293
|
+
};
|
|
25294
|
+
});
|
|
25264
25295
|
}, sels);
|
|
25265
25296
|
return raw.flatMap((item) => {
|
|
25266
25297
|
const cleaned = {
|
|
@@ -25302,54 +25333,115 @@ var init_PAAExtractor = __esm({
|
|
|
25302
25333
|
const seenQs = /* @__PURE__ */ new Set();
|
|
25303
25334
|
const orderedQs = [];
|
|
25304
25335
|
const results = [];
|
|
25305
|
-
const
|
|
25306
|
-
|
|
25307
|
-
|
|
25308
|
-
|
|
25309
|
-
|
|
25336
|
+
const abandonedNeverReclick = /* @__PURE__ */ new Set();
|
|
25337
|
+
const clickedOnceEver = /* @__PURE__ */ new Set();
|
|
25338
|
+
const itemArgs = {
|
|
25339
|
+
sel: PAASelectors.item,
|
|
25340
|
+
dataQ: PAASelectors.itemDataQ,
|
|
25341
|
+
dataInitQ: PAASelectors.itemDataInitQ,
|
|
25342
|
+
questionEl: PAASelectors.itemQuestionEl,
|
|
25343
|
+
answerSel: PAASelectors.answerContainer,
|
|
25344
|
+
expandedClass: PAASelectors.expandedClass,
|
|
25345
|
+
clickTarget: PAASelectors.clickTarget
|
|
25346
|
+
};
|
|
25347
|
+
const readItemStates = () => page.evaluate(
|
|
25348
|
+
({ sel, dataQ, dataInitQ, questionEl, expandedClass, answerSel }) => {
|
|
25349
|
+
const answerText = (root) => {
|
|
25350
|
+
if (!root) return "";
|
|
25351
|
+
let out = "";
|
|
25352
|
+
const walk = (n) => {
|
|
25353
|
+
for (const c of Array.from(n.childNodes)) {
|
|
25354
|
+
if (c.nodeType === Node.TEXT_NODE) out += c.textContent || "";
|
|
25355
|
+
else if (c.nodeType === Node.ELEMENT_NODE && c.tagName !== "STYLE" && c.tagName !== "SCRIPT") walk(c);
|
|
25356
|
+
}
|
|
25357
|
+
};
|
|
25358
|
+
walk(root);
|
|
25359
|
+
return out.replace(/\s+/g, " ").trim();
|
|
25360
|
+
};
|
|
25361
|
+
return Array.from(document.querySelectorAll(sel)).map((el2) => ({
|
|
25362
|
+
q: el2.getAttribute(dataQ) || el2.getAttribute(dataInitQ) || el2.querySelector(questionEl)?.innerText?.trim() || "",
|
|
25363
|
+
done: el2.classList.contains(expandedClass) || answerText(el2.querySelector(answerSel)).length > 30
|
|
25364
|
+
})).filter((s) => s.q);
|
|
25365
|
+
},
|
|
25366
|
+
itemArgs
|
|
25310
25367
|
);
|
|
25368
|
+
const expandOneItemSerially = async (q) => {
|
|
25369
|
+
const clicked = await page.evaluate(
|
|
25370
|
+
({ sel, dataQ, dataInitQ, clickTarget, q: target }) => {
|
|
25371
|
+
const item = Array.from(document.querySelectorAll(sel)).find((el2) => (el2.getAttribute(dataQ) || el2.getAttribute(dataInitQ)) === target);
|
|
25372
|
+
const btn = item?.querySelector(clickTarget);
|
|
25373
|
+
if (!btn) return false;
|
|
25374
|
+
btn.scrollIntoView({ block: "center" });
|
|
25375
|
+
btn.click();
|
|
25376
|
+
return true;
|
|
25377
|
+
},
|
|
25378
|
+
{ ...itemArgs, q }
|
|
25379
|
+
).catch(() => false);
|
|
25380
|
+
if (!clicked) return "failed";
|
|
25381
|
+
try {
|
|
25382
|
+
const outcome = await page.waitForFunction(
|
|
25383
|
+
({ sel, dataQ, dataInitQ, answerSel, q: target }) => {
|
|
25384
|
+
const answerText = (root) => {
|
|
25385
|
+
if (!root) return "";
|
|
25386
|
+
let out = "";
|
|
25387
|
+
const walk = (n) => {
|
|
25388
|
+
for (const c of Array.from(n.childNodes)) {
|
|
25389
|
+
if (c.nodeType === Node.TEXT_NODE) out += c.textContent || "";
|
|
25390
|
+
else if (c.nodeType === Node.ELEMENT_NODE && c.tagName !== "STYLE" && c.tagName !== "SCRIPT") walk(c);
|
|
25391
|
+
}
|
|
25392
|
+
};
|
|
25393
|
+
walk(root);
|
|
25394
|
+
return out.replace(/\s+/g, " ").trim();
|
|
25395
|
+
};
|
|
25396
|
+
const item = Array.from(document.querySelectorAll(sel)).find((el2) => (el2.getAttribute(dataQ) || el2.getAttribute(dataInitQ)) === target);
|
|
25397
|
+
if (!item) return "gone";
|
|
25398
|
+
const text = answerText(item.querySelector(answerSel));
|
|
25399
|
+
if (/an error has occurred/i.test(text.slice(0, 80))) return "error";
|
|
25400
|
+
if (text.length > 30) return "ok";
|
|
25401
|
+
return false;
|
|
25402
|
+
},
|
|
25403
|
+
{ ...itemArgs, q },
|
|
25404
|
+
{ timeout: 6500, polling: 200 }
|
|
25405
|
+
);
|
|
25406
|
+
return await outcome.jsonValue() === "ok" ? "ok" : "failed";
|
|
25407
|
+
} catch {
|
|
25408
|
+
return "failed";
|
|
25409
|
+
}
|
|
25410
|
+
};
|
|
25311
25411
|
let round = 0;
|
|
25312
|
-
|
|
25412
|
+
let growthWaits = 0;
|
|
25413
|
+
while (true) {
|
|
25313
25414
|
if (options.softDeadlineMs && Date.now() >= options.softDeadlineMs) break;
|
|
25314
25415
|
this.throwIfAborted(signal);
|
|
25315
|
-
|
|
25316
|
-
const
|
|
25317
|
-
|
|
25318
|
-
|
|
25319
|
-
|
|
25320
|
-
if (unexpandedCount === 0) break;
|
|
25321
|
-
this.reporter.onDepth(++round);
|
|
25322
|
-
for (let ci = 0; ci < unexpandedCount; ci++) {
|
|
25323
|
-
if (options.softDeadlineMs && Date.now() >= options.softDeadlineMs) break;
|
|
25324
|
-
this.throwIfAborted(signal);
|
|
25325
|
-
try {
|
|
25326
|
-
const btn = page.locator(unexpandedSel).first();
|
|
25327
|
-
await btn.scrollIntoViewIfNeeded();
|
|
25328
|
-
await btn.hover({ force: true });
|
|
25329
|
-
await page.waitForTimeout(100);
|
|
25330
|
-
await btn.click({ force: true });
|
|
25331
|
-
await page.waitForTimeout(500);
|
|
25332
|
-
} catch {
|
|
25416
|
+
const states = await readItemStates();
|
|
25417
|
+
for (const s of states) {
|
|
25418
|
+
if (!seenQs.has(s.q)) {
|
|
25419
|
+
seenQs.add(s.q);
|
|
25420
|
+
orderedQs.push(s.q);
|
|
25333
25421
|
}
|
|
25334
25422
|
}
|
|
25335
|
-
|
|
25336
|
-
|
|
25337
|
-
|
|
25338
|
-
|
|
25339
|
-
|
|
25340
|
-
|
|
25341
|
-
|
|
25342
|
-
|
|
25343
|
-
|
|
25344
|
-
|
|
25345
|
-
|
|
25346
|
-
|
|
25347
|
-
|
|
25348
|
-
}
|
|
25423
|
+
const kept = new Set(orderedQs.slice(0, options.maxQuestions));
|
|
25424
|
+
const clickable = states.filter((s) => kept.has(s.q) && !clickedOnceEver.has(s.q) && !abandonedNeverReclick.has(s.q));
|
|
25425
|
+
const target = clickable.find((s) => !s.done) ?? (seenQs.size < options.maxQuestions ? clickable[0] : void 0);
|
|
25426
|
+
if (!target) {
|
|
25427
|
+
if (seenQs.size >= options.maxQuestions) break;
|
|
25428
|
+
if (++growthWaits > 1) break;
|
|
25429
|
+
const grew = await page.waitForFunction(
|
|
25430
|
+
({ sel, min }) => document.querySelectorAll(sel).length > min,
|
|
25431
|
+
{ sel: PAASelectors.item, min: states.length },
|
|
25432
|
+
{ timeout: 3e3 }
|
|
25433
|
+
).catch(() => null);
|
|
25434
|
+
if (!grew) break;
|
|
25435
|
+
continue;
|
|
25349
25436
|
}
|
|
25437
|
+
growthWaits = 0;
|
|
25438
|
+
this.reporter.onDepth(++round);
|
|
25439
|
+
await this.throwIfCaptcha(page, "Google PAA expansion");
|
|
25440
|
+
clickedOnceEver.add(target.q);
|
|
25441
|
+
if (await expandOneItemSerially(target.q) === "failed") abandonedNeverReclick.add(target.q);
|
|
25350
25442
|
}
|
|
25351
25443
|
const itemMap = new Map((await this.extractVisibleItems(page)).map((i) => [i.question, i]));
|
|
25352
|
-
await this.fillIncompleteItems(page, orderedQs, itemMap, options);
|
|
25444
|
+
await this.fillIncompleteItems(page, orderedQs, itemMap, options, abandonedNeverReclick);
|
|
25353
25445
|
for (const q of orderedQs) {
|
|
25354
25446
|
if (results.length >= options.maxQuestions) break;
|
|
25355
25447
|
const key = this.normalizeQuestion(q);
|
|
@@ -25367,9 +25459,11 @@ var init_PAAExtractor = __esm({
|
|
|
25367
25459
|
this.completeness.paaWithoutSource = results.filter((r) => !r.source_title && !r.source_site && !r.source_cite).length;
|
|
25368
25460
|
return results;
|
|
25369
25461
|
}
|
|
25370
|
-
async fillIncompleteItems(page, orderedQs, itemMap, options) {
|
|
25462
|
+
async fillIncompleteItems(page, orderedQs, itemMap, options, abandonedNeverReclick) {
|
|
25371
25463
|
const kept = new Set(orderedQs.slice(0, options.maxQuestions));
|
|
25372
|
-
const missingBefore = new Set(
|
|
25464
|
+
const missingBefore = new Set(
|
|
25465
|
+
[...kept].filter((q) => !itemMap.get(q)?.answer && !abandonedNeverReclick?.has(q))
|
|
25466
|
+
);
|
|
25373
25467
|
if (missingBefore.size === 0) return;
|
|
25374
25468
|
for (let round = 0; round < 2; round++) {
|
|
25375
25469
|
if (options.softDeadlineMs && Date.now() >= options.softDeadlineMs) break;
|
|
@@ -25761,40 +25855,41 @@ var init_PAAExtractor = __esm({
|
|
|
25761
25855
|
};
|
|
25762
25856
|
}
|
|
25763
25857
|
async captureAIOverviewShareUrl(page, options) {
|
|
25764
|
-
|
|
25765
|
-
|
|
25766
|
-
const
|
|
25767
|
-
|
|
25768
|
-
|
|
25769
|
-
|
|
25770
|
-
|
|
25771
|
-
|
|
25772
|
-
|
|
25773
|
-
|
|
25774
|
-
|
|
25775
|
-
return true;
|
|
25776
|
-
}
|
|
25777
|
-
sec = sec.parentElement;
|
|
25858
|
+
if (options?.softDeadlineMs && Date.now() >= options.softDeadlineMs) return null;
|
|
25859
|
+
const clicked = await page.evaluate(() => {
|
|
25860
|
+
const heads = Array.from(document.querySelectorAll('h1,h2,h3,[role="heading"],div')).filter((h) => (h.textContent || "").trim() === "AI Overview");
|
|
25861
|
+
for (const head of heads) {
|
|
25862
|
+
let sec = head;
|
|
25863
|
+
for (let up = 0; up < 8 && sec; up++) {
|
|
25864
|
+
const btn = sec.querySelector('[aria-label="Share"]');
|
|
25865
|
+
if (btn) {
|
|
25866
|
+
btn.scrollIntoView({ block: "center" });
|
|
25867
|
+
btn.click();
|
|
25868
|
+
return true;
|
|
25778
25869
|
}
|
|
25870
|
+
sec = sec.parentElement;
|
|
25779
25871
|
}
|
|
25780
|
-
|
|
25781
|
-
|
|
25782
|
-
|
|
25783
|
-
|
|
25784
|
-
|
|
25872
|
+
}
|
|
25873
|
+
return false;
|
|
25874
|
+
}).catch(() => false);
|
|
25875
|
+
if (!clicked) return null;
|
|
25876
|
+
let url = null;
|
|
25877
|
+
try {
|
|
25878
|
+
const found = await page.waitForFunction(() => {
|
|
25785
25879
|
const w = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
25786
25880
|
while (w.nextNode()) {
|
|
25787
25881
|
const m = (w.currentNode.textContent || "").match(/https:\/\/share\.google\/aimode\/\S+/);
|
|
25788
25882
|
if (m) return m[0];
|
|
25789
25883
|
}
|
|
25790
|
-
return
|
|
25791
|
-
}
|
|
25792
|
-
await
|
|
25793
|
-
|
|
25794
|
-
|
|
25795
|
-
await page.waitForTimeout(600);
|
|
25884
|
+
return false;
|
|
25885
|
+
}, void 0, { timeout: 4500, polling: 250 });
|
|
25886
|
+
url = await found.jsonValue();
|
|
25887
|
+
} catch {
|
|
25888
|
+
url = null;
|
|
25796
25889
|
}
|
|
25797
|
-
|
|
25890
|
+
await page.keyboard.press("Escape").catch(() => {
|
|
25891
|
+
});
|
|
25892
|
+
return url;
|
|
25798
25893
|
}
|
|
25799
25894
|
buildTree(flat, _seed) {
|
|
25800
25895
|
const roots = [];
|
|
@@ -27305,7 +27400,7 @@ var PACKAGE_VERSION;
|
|
|
27305
27400
|
var init_version = __esm({
|
|
27306
27401
|
"src/version.ts"() {
|
|
27307
27402
|
"use strict";
|
|
27308
|
-
PACKAGE_VERSION = "0.
|
|
27403
|
+
PACKAGE_VERSION = "0.7.0";
|
|
27309
27404
|
}
|
|
27310
27405
|
});
|
|
27311
27406
|
|
|
@@ -27404,7 +27499,7 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
|
|
|
27404
27499
|
read it back for full detail rather than expecting the whole payload inline.
|
|
27405
27500
|
|
|
27406
27501
|
## Memory
|
|
27407
|
-
mcp-scraper also exposes
|
|
27502
|
+
mcp-scraper also exposes persistent per-user memory tools (notes, facts, vaults,
|
|
27408
27503
|
scheduled actions, tables, channels) backed by memory.mcpscraper.dev. Every account starts with 13
|
|
27409
27504
|
vaults \u2014 call **list-vaults** to see what exists before creating anything new. Pick the vault whose job
|
|
27410
27505
|
matches the content: **Ideas** (unvalidated concepts), **Knowledge** (distilled lessons/how-tos),
|
|
@@ -27414,11 +27509,45 @@ matches the content: **Ideas** (unvalidated concepts), **Knowledge** (distilled
|
|
|
27414
27509
|
**Improvement Log** (receipts of changes made and whether they worked), **Experiments** (hypothesis +
|
|
27415
27510
|
measured result), **Sprint** (current cycle's scope), **Inspiration** (other people's work worth
|
|
27416
27511
|
studying).
|
|
27417
|
-
|
|
27418
|
-
|
|
27512
|
+
For a normal new narrative note, call **prepare-memory-write** first. It queries the live vault contract,
|
|
27513
|
+
tag vocabulary, and natural neighbor vaults, and returns interlink candidates that must be read before
|
|
27514
|
+
acceptance. Compose every returned template section, then call **memory-capture**, which validates the
|
|
27515
|
+
note, registers canonical tags, writes it, and verifies readback. Reserve low-level **memory-put** for
|
|
27516
|
+
deliberate edits and migrations. Use
|
|
27419
27517
|
**table-create**/**table-insert-rows**/**table-query** instead when the caller wants row-shaped data
|
|
27420
27518
|
they'll filter/sort by exact value. **memory-search** is meaning-based over full content (embeds, slower);
|
|
27421
27519
|
**memory-list** filters one vault by kind/tags (fast, exact).
|
|
27520
|
+
|
|
27521
|
+
Treat every memory create or update as a graph operation. **prepare-memory-write** supplies the initial
|
|
27522
|
+
shortlist; use **memory-search** when it is weak or the topic is broad, and **memory-get** to read the best
|
|
27523
|
+
candidates in full. Add only links supported by the notes: same-
|
|
27524
|
+
vault targets go in props.related and natural [[path]] body links; cross-vault targets go in
|
|
27525
|
+
props.related_vault_notes as Vault Name::relative/path.md. Prefer existing People/Projects/system
|
|
27526
|
+
hubs and fewer strong links. Do not trust a background linker to repair a weak write.
|
|
27527
|
+
|
|
27528
|
+
Use the target vault's template, not generic prose. Always set summary, specific reusable tags,
|
|
27529
|
+
source_type, source_ref, related, related_vault_notes, embed, embed_priority, and a valid
|
|
27530
|
+
status; include vault-specific props when relevant. Body patterns: Knowledge = Thesis / Explanation /
|
|
27531
|
+
Examples / Implications; Library = Source Identity / Preserved Material / Extraction Notes; People =
|
|
27532
|
+
Identity / Relationship / Known Context / Interaction History / Open Loops; Projects = Purpose / Current
|
|
27533
|
+
State / Architecture / Open Work / Decisions; Issues = Observation / Impact / Confirmation / Evidence /
|
|
27534
|
+
Resolution; Improvement Log = Improvement / Issue Link / Change Made / Verification / Result. Keep Tasks,
|
|
27535
|
+
Calendar, Communications, Ideas, Inspiration, Experiments, and Sprint aligned to their named purpose.
|
|
27536
|
+
Tags are live vocabulary, not improvised labels: **list-memory-tags** shows what exists and
|
|
27537
|
+
**resolve-memory-tags** returns reuse/create/omit. A new tag is justified only when the concept is central,
|
|
27538
|
+
reusable, and has no exact, alias, or near-equivalent. Use **memory-backlinks**,
|
|
27539
|
+
**memory-graph-universe**, and **memory-graph-path** to trace the linked universe across vaults.
|
|
27540
|
+
|
|
27541
|
+
Scrape deposits are raw evidence and therefore go to **Library** through **library-ingest**, with the full
|
|
27542
|
+
Library template and source metadata. If the source contains durable applicable guidance, create a separate
|
|
27543
|
+
Knowledge companion through prepare-memory-write + memory-capture and link it to the Library source with
|
|
27544
|
+
derived_from; do not replace the raw source with the guide.
|
|
27545
|
+
|
|
27546
|
+
For an update, call **memory-get** first and pass its revision as baseRevision. Preserve the existing
|
|
27547
|
+
title, source, capture time, content context, and props unless the request deliberately changes them.
|
|
27548
|
+
If a legacy backend does not return props, do not overwrite an existing linked note through that surface;
|
|
27549
|
+
report that link preservation cannot be proved. After the write, read it back and search a distinctive
|
|
27550
|
+
phrase to verify persistence and indexing.
|
|
27422
27551
|
`.trim();
|
|
27423
27552
|
}
|
|
27424
27553
|
var SERVER_INSTRUCTIONS;
|
|
@@ -28841,7 +28970,7 @@ function localPlanningToolAnnotations(title) {
|
|
|
28841
28970
|
}
|
|
28842
28971
|
function listSavedReports() {
|
|
28843
28972
|
try {
|
|
28844
|
-
const dir =
|
|
28973
|
+
const dir = outputBaseDir();
|
|
28845
28974
|
return (0, import_node_fs9.readdirSync)(dir).filter((f) => f.endsWith(".md")).map((f) => ({ filename: f, mtimeMs: (0, import_node_fs9.statSync)((0, import_node_path12.join)(dir, f)).mtimeMs })).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, 100);
|
|
28846
28975
|
} catch {
|
|
28847
28976
|
return [];
|
|
@@ -28868,7 +28997,7 @@ function registerSavedReportResources(server) {
|
|
|
28868
28997
|
const requested = Array.isArray(variables.filename) ? variables.filename[0] : variables.filename;
|
|
28869
28998
|
const filename = (0, import_node_path12.basename)(decodeURIComponent(String(requested ?? "")));
|
|
28870
28999
|
if (!filename.endsWith(".md")) throw new Error("Only saved .md reports can be read");
|
|
28871
|
-
const text = (0, import_node_fs9.readFileSync)((0, import_node_path12.join)(
|
|
29000
|
+
const text = (0, import_node_fs9.readFileSync)((0, import_node_path12.join)(outputBaseDir(), filename), "utf8");
|
|
28872
29001
|
return { contents: [{ uri: uri.href, mimeType: "text/markdown", text }] };
|
|
28873
29002
|
}
|
|
28874
29003
|
);
|
|
@@ -29467,7 +29596,7 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
29467
29596
|
});
|
|
29468
29597
|
|
|
29469
29598
|
// src/services/fanout/export.ts
|
|
29470
|
-
function
|
|
29599
|
+
function outputBaseDir2() {
|
|
29471
29600
|
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || (0, import_node_path13.join)((0, import_node_os8.homedir)(), "Downloads", "mcp-scraper");
|
|
29472
29601
|
}
|
|
29473
29602
|
function safe(value) {
|
|
@@ -29478,7 +29607,7 @@ function writeTable(path6, rows, delimiter) {
|
|
|
29478
29607
|
}
|
|
29479
29608
|
function exportFanout(enriched) {
|
|
29480
29609
|
const stamp = safe(enriched.capturedAt.replace(/[:.]/g, "-"));
|
|
29481
|
-
const outputDir =
|
|
29610
|
+
const outputDir = outputBaseDir2();
|
|
29482
29611
|
const relativeDir = (0, import_node_path13.join)("fanout", `${stamp}-${safe(enriched.platform)}`);
|
|
29483
29612
|
const dir = (0, import_node_path13.join)(outputDir, relativeDir);
|
|
29484
29613
|
(0, import_node_fs10.mkdirSync)(dir, { recursive: true });
|
|
@@ -30212,10 +30341,10 @@ function ffmpegFilterPath(path6) {
|
|
|
30212
30341
|
async function annotateReplayVideo(inputFilePath, outputFilePath, options) {
|
|
30213
30342
|
if (!options.annotations.length) throw new Error("annotations must include at least one item");
|
|
30214
30343
|
const size = await videoSize(inputFilePath);
|
|
30215
|
-
const tmp = await (0,
|
|
30344
|
+
const tmp = await (0, import_promises9.mkdtemp)((0, import_node_path14.join)((0, import_node_os9.tmpdir)(), "mcp-scraper-ass-"));
|
|
30216
30345
|
const assPath = (0, import_node_path14.join)(tmp, "annotations.ass");
|
|
30217
30346
|
try {
|
|
30218
|
-
await (0,
|
|
30347
|
+
await (0, import_promises9.writeFile)(assPath, buildAssSubtitle(options, size), "utf8");
|
|
30219
30348
|
await execFileAsync2("ffmpeg", [
|
|
30220
30349
|
"-y",
|
|
30221
30350
|
"-i",
|
|
@@ -30232,7 +30361,7 @@ async function annotateReplayVideo(inputFilePath, outputFilePath, options) {
|
|
|
30232
30361
|
"copy",
|
|
30233
30362
|
outputFilePath
|
|
30234
30363
|
], { maxBuffer: 1024 * 1024 * 20 });
|
|
30235
|
-
const out = await (0,
|
|
30364
|
+
const out = await (0, import_promises9.stat)(outputFilePath);
|
|
30236
30365
|
return {
|
|
30237
30366
|
filePath: outputFilePath,
|
|
30238
30367
|
bytes: out.size,
|
|
@@ -30241,15 +30370,15 @@ async function annotateReplayVideo(inputFilePath, outputFilePath, options) {
|
|
|
30241
30370
|
annotationCount: options.annotations.length
|
|
30242
30371
|
};
|
|
30243
30372
|
} finally {
|
|
30244
|
-
await (0,
|
|
30373
|
+
await (0, import_promises9.rm)(tmp, { recursive: true, force: true });
|
|
30245
30374
|
}
|
|
30246
30375
|
}
|
|
30247
|
-
var import_node_child_process4,
|
|
30376
|
+
var import_node_child_process4, import_promises9, import_node_os9, import_node_path14, import_node_util2, execFileAsync2;
|
|
30248
30377
|
var init_replay_annotator = __esm({
|
|
30249
30378
|
"src/mcp/replay-annotator.ts"() {
|
|
30250
30379
|
"use strict";
|
|
30251
30380
|
import_node_child_process4 = require("child_process");
|
|
30252
|
-
|
|
30381
|
+
import_promises9 = require("fs/promises");
|
|
30253
30382
|
import_node_os9 = require("os");
|
|
30254
30383
|
import_node_path14 = require("path");
|
|
30255
30384
|
import_node_util2 = require("util");
|
|
@@ -30294,7 +30423,7 @@ function actionResult(tool, sessionId, ok, data, nextRecommendedTool = "browser_
|
|
|
30294
30423
|
nextRecommendedTool
|
|
30295
30424
|
});
|
|
30296
30425
|
}
|
|
30297
|
-
function
|
|
30426
|
+
function outputBaseDir3() {
|
|
30298
30427
|
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || (0, import_node_path15.join)((0, import_node_os10.homedir)(), "Downloads", "mcp-scraper");
|
|
30299
30428
|
}
|
|
30300
30429
|
function safeFilePart2(value) {
|
|
@@ -30304,7 +30433,7 @@ function replayFilePath(sessionId, replayId, filename) {
|
|
|
30304
30433
|
const requested = filename?.trim();
|
|
30305
30434
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
30306
30435
|
const name = requested ? safeFilePart2(requested).replace(/\.mp4$/i, "") : `${stamp}-${safeFilePart2(sessionId)}-${safeFilePart2(replayId)}`;
|
|
30307
|
-
return (0, import_node_path15.join)(
|
|
30436
|
+
return (0, import_node_path15.join)(outputBaseDir3(), "browser-replays", `${name}.mp4`);
|
|
30308
30437
|
}
|
|
30309
30438
|
function slugPart(value) {
|
|
30310
30439
|
const trimmed = value?.trim().toLowerCase();
|
|
@@ -30383,7 +30512,7 @@ function registerBrowserAgentMcpTools(server, opts) {
|
|
|
30383
30512
|
}
|
|
30384
30513
|
const bytes = Buffer.from(await res.arrayBuffer());
|
|
30385
30514
|
const filePath = replayFilePath(sessionId, replayId, filename);
|
|
30386
|
-
(0, import_node_fs11.mkdirSync)((0, import_node_path15.join)(
|
|
30515
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path15.join)(outputBaseDir3(), "browser-replays"), { recursive: true });
|
|
30387
30516
|
(0, import_node_fs11.writeFileSync)(filePath, bytes);
|
|
30388
30517
|
return {
|
|
30389
30518
|
ok: true,
|
|
@@ -30933,7 +31062,7 @@ function registerBrowserAgentMcpTools(server, opts) {
|
|
|
30933
31062
|
try {
|
|
30934
31063
|
const sourcePath = String(downloaded.data.file_path);
|
|
30935
31064
|
const outputPath = annotatedReplayFilePath(input.session_id, input.replay_id, input.filename);
|
|
30936
|
-
(0, import_node_fs11.mkdirSync)((0, import_node_path15.join)(
|
|
31065
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path15.join)(outputBaseDir3(), "browser-replays"), { recursive: true });
|
|
30937
31066
|
const result = await annotateReplayVideo(sourcePath, outputPath, {
|
|
30938
31067
|
annotations: input.annotations,
|
|
30939
31068
|
sourceWidth: input.source_width,
|
|
@@ -31078,7 +31207,7 @@ var init_browser_agent_mcp_server = __esm({
|
|
|
31078
31207
|
});
|
|
31079
31208
|
|
|
31080
31209
|
// src/mcp/memory-tool-schemas.ts
|
|
31081
|
-
var import_zod35, AcceptShareSchema, ApproveSenderSchema, DeclineShareSchema, GetChatLinkSchema, InboxSettingsSchema, InviteAccountSchema, issueKeyTool_scopeShape, IssueKeySchema, ListApprovedSendersSchema, ListKeysSchema, NoteInboxSchema, RemoveApprovedSenderSchema, RevokeChatLinkSchema, RevokeKeySchema, RevokeShareSchema, SetAgentIdentitySchema, SetScopeSchema, ShareNoteSchema, ShareVaultSchema, SwapVaultSchema, SwitchAccountSchema, UnlinkShareSchema, MemoryQuestionsSchema, CreateChannelSchema, GetMessageNoteSchema, ListChannelMembersSchema, ListChannelMessagesSchema, MyMentionsSchema, PollChannelSchema, PostMessageSchema, ReactMessageSchema, RemoveChannelMemberSchema, ReplyMessageSchema, factHistoryTool_entryShape, FactHistorySchema, recordFactTool_factShape, RecordFactSchema, LibraryIngestSchema, DeleteNoteSchema, ExportSchema, GetSchema, ListSchema,
|
|
31210
|
+
var import_zod35, AcceptShareSchema, ApproveSenderSchema, DeclineShareSchema, GetChatLinkSchema, InboxSettingsSchema, InviteAccountSchema, issueKeyTool_scopeShape, IssueKeySchema, ListApprovedSendersSchema, ListKeysSchema, NoteInboxSchema, RemoveApprovedSenderSchema, RevokeChatLinkSchema, RevokeKeySchema, RevokeShareSchema, SetAgentIdentitySchema, SetScopeSchema, ShareNoteSchema, ShareVaultSchema, SwapVaultSchema, SwitchAccountSchema, UnlinkShareSchema, memoryCaptureTool_notePropsSchema, MemoryCaptureSchema, MemoryQuestionsSchema, PrepareMemoryWriteSchema, validateMemoryWriteTool_notePropsSchema, ValidateMemoryWriteSchema, CreateChannelSchema, GetMessageNoteSchema, ListChannelMembersSchema, ListChannelMessagesSchema, MyMentionsSchema, PollChannelSchema, PostMessageSchema, ReactMessageSchema, RemoveChannelMemberSchema, ReplyMessageSchema, factHistoryTool_entryShape, FactHistorySchema, recordFactTool_factShape, RecordFactSchema, NoteBacklinksSchema, GraphPathSchema, GraphUniverseSchema, LibraryIngestSchema, DeleteNoteSchema, ExportSchema, getTool_notePropsSchema, GetSchema, ListSchema, putTool_notePropsSchema, PutSchema, SearchSchema, SuggestSchema, UploadSchema, TemporalRecallSchema, CreateScheduledActionSchema, DeleteScheduledActionSchema, GetScheduleLinkSchema, GetScheduleStatusSchema, ListScheduledActionsSchema, PauseScheduledActionSchema, ProposeScheduledActionSchema, ResumeScheduledActionSchema, RevokeScheduleLinkSchema, SetScheduleEntitlementSchema, CostUsageSchema, StorageUsageSchema, CreateTableSchema, deleteTableRowsTool_FilterSchema, DeleteTableRowsSchema, DescribeTableSchema, DropTableSchema, InsertTableRowsSchema, ListTablesSchema, queryTableTool_FilterSchema, QueryTableSchema, ListTagsSchema, ResolveTagsSchema, UpsertTagSchema, AddVaultSchema, CreateSecureVaultSchema, DeleteVaultSchema, GetVaultContractSchema, ListSharedWithMeSchema, ListVaultsSchema, ProvisionDefaultsSchema, RouteMemorySchema, VideoAnalyzeStartSchema, VideoAnalyzeStatusSchema, CreateWebhookSchema, ListWebhooksSchema, RevokeWebhookSchema, MEMORY_TOOL_SCHEMAS;
|
|
31082
31211
|
var init_memory_tool_schemas = __esm({
|
|
31083
31212
|
"src/mcp/memory-tool-schemas.ts"() {
|
|
31084
31213
|
"use strict";
|
|
@@ -31587,6 +31716,52 @@ var init_memory_tool_schemas = __esm({
|
|
|
31587
31716
|
openWorldHint: false
|
|
31588
31717
|
}
|
|
31589
31718
|
};
|
|
31719
|
+
memoryCaptureTool_notePropsSchema = import_zod35.z.object({
|
|
31720
|
+
status: import_zod35.z.string().describe("Status enum value from the target vault contract."),
|
|
31721
|
+
summary: import_zod35.z.string().describe("Short retrieval-ready description."),
|
|
31722
|
+
tags: import_zod35.z.array(import_zod35.z.string()).describe("AI-generated keyword tags, not vault names."),
|
|
31723
|
+
pinned: import_zod35.z.boolean().describe("Recall boost for important notes."),
|
|
31724
|
+
source_type: import_zod35.z.string().describe("Attribution kind: user, person, url, file, channel, thread, or note."),
|
|
31725
|
+
source_ref: import_zod35.z.string().describe("Attribution reference (URL, path, channel, thread, or source note)."),
|
|
31726
|
+
related: import_zod35.z.array(import_zod35.z.string()).describe("Same-vault links (wiki [[ ]] targets)."),
|
|
31727
|
+
related_vault_notes: import_zod35.z.array(import_zod35.z.string()).describe('Cross-vault references in "Vault Name::relative/path.md" form.'),
|
|
31728
|
+
embed: import_zod35.z.boolean().describe("Whether Smart RAG should index the note."),
|
|
31729
|
+
embed_priority: import_zod35.z.enum(["low", "normal", "high"]).describe("Embedding priority."),
|
|
31730
|
+
embedding_summary: import_zod35.z.string().describe("Optional retrieval-specific summary."),
|
|
31731
|
+
type: import_zod35.z.string().describe("Note type from the target vault contract (also used to route the note)."),
|
|
31732
|
+
domain: import_zod35.z.string().describe("Domain folder for Library/Knowledge (AI, SEO, Copywriting & Ads, Business, Spirituality)."),
|
|
31733
|
+
folder: import_zod35.z.string().describe("Explicit sub-folder within the vault; overrides routing-derived folder."),
|
|
31734
|
+
parentMessageId: import_zod35.z.string().describe("Channel messages only: the path of the top-level message this is a reply to. Absent on top-level messages.")
|
|
31735
|
+
}).partial().passthrough();
|
|
31736
|
+
MemoryCaptureSchema = {
|
|
31737
|
+
id: "memory-capture",
|
|
31738
|
+
upstreamName: "memoryCaptureTool",
|
|
31739
|
+
description: "Strict normal-create path for durable memory. Refuses incomplete notes, writes through memory-put, registers canonical tags, and reads the note back to verify persisted content and props. Call prepare-memory-write first. Reserve memory-put for low-level migrations or deliberate edits.",
|
|
31740
|
+
input: {
|
|
31741
|
+
vault: import_zod35.z.string(),
|
|
31742
|
+
folder: import_zod35.z.string().optional(),
|
|
31743
|
+
path: import_zod35.z.string().min(1),
|
|
31744
|
+
title: import_zod35.z.string().min(1),
|
|
31745
|
+
content: import_zod35.z.string().min(1),
|
|
31746
|
+
props: memoryCaptureTool_notePropsSchema,
|
|
31747
|
+
baseRevision: import_zod35.z.number().optional(),
|
|
31748
|
+
tagDecisions: import_zod35.z.array(import_zod35.z.object({ tag: import_zod35.z.string().min(1), central: import_zod35.z.boolean(), reusable: import_zod35.z.boolean(), description: import_zod35.z.string().optional() })).max(8).optional().describe("Required justification for any tag that does not already exist. Existing exact/alias/near tags are canonicalized automatically; a new tag is accepted only when its matching decision has central=true and reusable=true.")
|
|
31749
|
+
},
|
|
31750
|
+
output: {
|
|
31751
|
+
ok: import_zod35.z.boolean(),
|
|
31752
|
+
valid: import_zod35.z.boolean().optional(),
|
|
31753
|
+
errors: import_zod35.z.array(import_zod35.z.string()).optional(),
|
|
31754
|
+
warnings: import_zod35.z.array(import_zod35.z.string()).optional(),
|
|
31755
|
+
tagResolutions: import_zod35.z.array(import_zod35.z.object({ candidate: import_zod35.z.string(), action: import_zod35.z.enum(["reuse", "create", "omit"]), tag: import_zod35.z.string().optional(), reason: import_zod35.z.string() })).optional(),
|
|
31756
|
+
note: import_zod35.z.object({ path: import_zod35.z.string(), title: import_zod35.z.string(), updatedAt: import_zod35.z.string(), revision: import_zod35.z.number() }).optional(),
|
|
31757
|
+
indexed: import_zod35.z.number().optional(),
|
|
31758
|
+
verified: import_zod35.z.object({ contentBytes: import_zod35.z.number(), propsPersisted: import_zod35.z.boolean(), revision: import_zod35.z.number() }).optional(),
|
|
31759
|
+
conflict: import_zod35.z.boolean().optional(),
|
|
31760
|
+
code: import_zod35.z.string().optional(),
|
|
31761
|
+
error: import_zod35.z.string().optional()
|
|
31762
|
+
},
|
|
31763
|
+
annotations: { title: "Capture Governed Memory", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
31764
|
+
};
|
|
31590
31765
|
MemoryQuestionsSchema = {
|
|
31591
31766
|
id: "memory-questions",
|
|
31592
31767
|
upstreamName: "memoryQuestionsTool",
|
|
@@ -31616,6 +31791,67 @@ var init_memory_tool_schemas = __esm({
|
|
|
31616
31791
|
openWorldHint: true
|
|
31617
31792
|
}
|
|
31618
31793
|
};
|
|
31794
|
+
PrepareMemoryWriteSchema = {
|
|
31795
|
+
id: "prepare-memory-write",
|
|
31796
|
+
upstreamName: "prepareMemoryWriteTool",
|
|
31797
|
+
description: "Mandatory planning pass for a normal new memory. Routes the note, returns the live template and natural vault relationships, resolves proposed tags against the registry, and shortlists interlink opportunities that must be read/reviewed before capture.",
|
|
31798
|
+
input: {
|
|
31799
|
+
title: import_zod35.z.string().min(1),
|
|
31800
|
+
content: import_zod35.z.string().min(1),
|
|
31801
|
+
source: import_zod35.z.string().optional(),
|
|
31802
|
+
type: import_zod35.z.string().optional(),
|
|
31803
|
+
vault: import_zod35.z.string().optional(),
|
|
31804
|
+
tagCandidates: import_zod35.z.array(import_zod35.z.object({ tag: import_zod35.z.string().min(1), central: import_zod35.z.boolean().optional(), reusable: import_zod35.z.boolean().optional(), description: import_zod35.z.string().optional() })).max(20).optional(),
|
|
31805
|
+
maxLinks: import_zod35.z.number().int().min(1).max(20).optional()
|
|
31806
|
+
},
|
|
31807
|
+
output: {
|
|
31808
|
+
ok: import_zod35.z.boolean(),
|
|
31809
|
+
route: import_zod35.z.record(import_zod35.z.unknown()).optional(),
|
|
31810
|
+
contract: import_zod35.z.record(import_zod35.z.unknown()).optional(),
|
|
31811
|
+
tagResolutions: import_zod35.z.array(import_zod35.z.record(import_zod35.z.unknown())).optional(),
|
|
31812
|
+
linkOpportunities: import_zod35.z.array(import_zod35.z.record(import_zod35.z.unknown())).optional(),
|
|
31813
|
+
instructions: import_zod35.z.array(import_zod35.z.string()).optional(),
|
|
31814
|
+
error: import_zod35.z.string().optional()
|
|
31815
|
+
},
|
|
31816
|
+
annotations: { title: "Prepare Memory Write", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
31817
|
+
};
|
|
31818
|
+
validateMemoryWriteTool_notePropsSchema = import_zod35.z.object({
|
|
31819
|
+
status: import_zod35.z.string().describe("Status enum value from the target vault contract."),
|
|
31820
|
+
summary: import_zod35.z.string().describe("Short retrieval-ready description."),
|
|
31821
|
+
tags: import_zod35.z.array(import_zod35.z.string()).describe("AI-generated keyword tags, not vault names."),
|
|
31822
|
+
pinned: import_zod35.z.boolean().describe("Recall boost for important notes."),
|
|
31823
|
+
source_type: import_zod35.z.string().describe("Attribution kind: user, person, url, file, channel, thread, or note."),
|
|
31824
|
+
source_ref: import_zod35.z.string().describe("Attribution reference (URL, path, channel, thread, or source note)."),
|
|
31825
|
+
related: import_zod35.z.array(import_zod35.z.string()).describe("Same-vault links (wiki [[ ]] targets)."),
|
|
31826
|
+
related_vault_notes: import_zod35.z.array(import_zod35.z.string()).describe('Cross-vault references in "Vault Name::relative/path.md" form.'),
|
|
31827
|
+
embed: import_zod35.z.boolean().describe("Whether Smart RAG should index the note."),
|
|
31828
|
+
embed_priority: import_zod35.z.enum(["low", "normal", "high"]).describe("Embedding priority."),
|
|
31829
|
+
embedding_summary: import_zod35.z.string().describe("Optional retrieval-specific summary."),
|
|
31830
|
+
type: import_zod35.z.string().describe("Note type from the target vault contract (also used to route the note)."),
|
|
31831
|
+
domain: import_zod35.z.string().describe("Domain folder for Library/Knowledge (AI, SEO, Copywriting & Ads, Business, Spirituality)."),
|
|
31832
|
+
folder: import_zod35.z.string().describe("Explicit sub-folder within the vault; overrides routing-derived folder."),
|
|
31833
|
+
parentMessageId: import_zod35.z.string().describe("Channel messages only: the path of the top-level message this is a reply to. Absent on top-level messages.")
|
|
31834
|
+
}).partial().passthrough();
|
|
31835
|
+
ValidateMemoryWriteSchema = {
|
|
31836
|
+
id: "validate-memory-write",
|
|
31837
|
+
upstreamName: "validateMemoryWriteTool",
|
|
31838
|
+
description: "Validate a proposed governed note without writing it. Checks template completeness, vault status/type, canonical tag count, attribution, Obsidian link primitives, and retrieval metadata.",
|
|
31839
|
+
input: {
|
|
31840
|
+
vault: import_zod35.z.string(),
|
|
31841
|
+
title: import_zod35.z.string(),
|
|
31842
|
+
content: import_zod35.z.string(),
|
|
31843
|
+
props: validateMemoryWriteTool_notePropsSchema
|
|
31844
|
+
},
|
|
31845
|
+
output: {
|
|
31846
|
+
ok: import_zod35.z.boolean(),
|
|
31847
|
+
valid: import_zod35.z.boolean().optional(),
|
|
31848
|
+
errors: import_zod35.z.array(import_zod35.z.string()).optional(),
|
|
31849
|
+
warnings: import_zod35.z.array(import_zod35.z.string()).optional(),
|
|
31850
|
+
normalizedTags: import_zod35.z.array(import_zod35.z.string()).optional(),
|
|
31851
|
+
error: import_zod35.z.string().optional()
|
|
31852
|
+
},
|
|
31853
|
+
annotations: { title: "Validate Memory Write", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
31854
|
+
};
|
|
31619
31855
|
CreateChannelSchema = {
|
|
31620
31856
|
id: "create-channel",
|
|
31621
31857
|
upstreamName: "createChannelTool",
|
|
@@ -31956,18 +32192,78 @@ var init_memory_tool_schemas = __esm({
|
|
|
31956
32192
|
openWorldHint: false
|
|
31957
32193
|
}
|
|
31958
32194
|
};
|
|
32195
|
+
NoteBacklinksSchema = {
|
|
32196
|
+
id: "memory-backlinks",
|
|
32197
|
+
upstreamName: "noteBacklinksTool",
|
|
32198
|
+
description: "Return every resolved incoming link to a note across all accessible vaults, including typed metadata links and Obsidian wiki links.",
|
|
32199
|
+
input: {
|
|
32200
|
+
note: import_zod35.z.string().min(1),
|
|
32201
|
+
vault: import_zod35.z.string().optional()
|
|
32202
|
+
},
|
|
32203
|
+
output: {
|
|
32204
|
+
ok: import_zod35.z.boolean(),
|
|
32205
|
+
nodes: import_zod35.z.array(import_zod35.z.object({ id: import_zod35.z.string(), vault: import_zod35.z.string(), path: import_zod35.z.string(), title: import_zod35.z.string(), resolved: import_zod35.z.boolean() })).optional(),
|
|
32206
|
+
edges: import_zod35.z.array(import_zod35.z.object({ source: import_zod35.z.string(), target: import_zod35.z.string(), type: import_zod35.z.string(), evidence: import_zod35.z.string(), sourceField: import_zod35.z.string(), resolved: import_zod35.z.boolean() })).optional(),
|
|
32207
|
+
error: import_zod35.z.string().optional()
|
|
32208
|
+
},
|
|
32209
|
+
annotations: { title: "Memory Backlinks", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
32210
|
+
};
|
|
32211
|
+
GraphPathSchema = {
|
|
32212
|
+
id: "memory-graph-path",
|
|
32213
|
+
upstreamName: "graphPathTool",
|
|
32214
|
+
description: "Find the shortest navigable connection between two memory notes across vault boundaries. Returns an empty graph when no path exists within maxDepth.",
|
|
32215
|
+
input: {
|
|
32216
|
+
from: import_zod35.z.string().min(1),
|
|
32217
|
+
to: import_zod35.z.string().min(1),
|
|
32218
|
+
fromVault: import_zod35.z.string().optional(),
|
|
32219
|
+
toVault: import_zod35.z.string().optional(),
|
|
32220
|
+
maxDepth: import_zod35.z.number().int().min(1).max(12).optional()
|
|
32221
|
+
},
|
|
32222
|
+
output: {
|
|
32223
|
+
ok: import_zod35.z.boolean(),
|
|
32224
|
+
nodes: import_zod35.z.array(import_zod35.z.object({ id: import_zod35.z.string(), vault: import_zod35.z.string(), path: import_zod35.z.string(), title: import_zod35.z.string(), resolved: import_zod35.z.boolean() })).optional(),
|
|
32225
|
+
edges: import_zod35.z.array(import_zod35.z.object({ source: import_zod35.z.string(), target: import_zod35.z.string(), type: import_zod35.z.string(), evidence: import_zod35.z.string(), sourceField: import_zod35.z.string(), resolved: import_zod35.z.boolean() })).optional(),
|
|
32226
|
+
error: import_zod35.z.string().optional()
|
|
32227
|
+
},
|
|
32228
|
+
annotations: { title: "Memory Graph Path", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
32229
|
+
};
|
|
32230
|
+
GraphUniverseSchema = {
|
|
32231
|
+
id: "memory-graph-universe",
|
|
32232
|
+
upstreamName: "graphUniverseTool",
|
|
32233
|
+
description: "Traverse the interlinked memory universe around one note in every direction, like an Obsidian local graph. Returns nodes and typed edges to a bounded depth.",
|
|
32234
|
+
input: {
|
|
32235
|
+
note: import_zod35.z.string().min(1),
|
|
32236
|
+
vault: import_zod35.z.string().optional(),
|
|
32237
|
+
depth: import_zod35.z.number().int().min(0).max(6).optional(),
|
|
32238
|
+
maxNodes: import_zod35.z.number().int().min(1).max(500).optional()
|
|
32239
|
+
},
|
|
32240
|
+
output: {
|
|
32241
|
+
ok: import_zod35.z.boolean(),
|
|
32242
|
+
root: import_zod35.z.string().optional(),
|
|
32243
|
+
depth: import_zod35.z.number().optional(),
|
|
32244
|
+
truncated: import_zod35.z.boolean().optional(),
|
|
32245
|
+
nodes: import_zod35.z.array(import_zod35.z.object({ id: import_zod35.z.string(), vault: import_zod35.z.string(), path: import_zod35.z.string(), title: import_zod35.z.string(), resolved: import_zod35.z.boolean() })).optional(),
|
|
32246
|
+
edges: import_zod35.z.array(import_zod35.z.object({ source: import_zod35.z.string(), target: import_zod35.z.string(), type: import_zod35.z.string(), evidence: import_zod35.z.string(), sourceField: import_zod35.z.string(), resolved: import_zod35.z.boolean() })).optional(),
|
|
32247
|
+
error: import_zod35.z.string().optional()
|
|
32248
|
+
},
|
|
32249
|
+
annotations: { title: "Memory Graph Universe", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
32250
|
+
};
|
|
31959
32251
|
LibraryIngestSchema = {
|
|
31960
32252
|
id: "library-ingest",
|
|
31961
32253
|
upstreamName: "libraryIngestTool",
|
|
31962
32254
|
description: "Deposit a scrape, transcript, or generated output into the tenant Library vault for later semantic recall. Content is embedded for per-tenant search and best-effort mirrored to a local vault when configured. Requires write scope on the target vault.",
|
|
31963
32255
|
input: {
|
|
31964
32256
|
vault: import_zod35.z.string().optional().describe(
|
|
31965
|
-
|
|
32257
|
+
"Vault to deposit into. Optional and normally omitted: raw scrapes always default to Library. Override only for a deliberate nonstandard migration."
|
|
31966
32258
|
),
|
|
31967
32259
|
title: import_zod35.z.string().min(1).describe("Short human-readable title for the item; used to build the stored path. Must be non-empty."),
|
|
31968
32260
|
content: import_zod35.z.string().min(1).describe("The full captured text (scrape/transcript/output) to store and index. Must be non-empty."),
|
|
31969
32261
|
source: import_zod35.z.string().min(1).describe("Provenance of the content, e.g. a URL or tool name. Must be non-empty."),
|
|
31970
32262
|
capturedAt: import_zod35.z.string().optional().describe("ISO-8601 capture timestamp. Optional; defaults to now. Also seeds the deterministic storage path."),
|
|
32263
|
+
summary: import_zod35.z.string().optional().describe("Retrieval-ready source summary. Optional; a provenance summary is generated when omitted."),
|
|
32264
|
+
tags: import_zod35.z.array(import_zod35.z.string()).max(8).optional().describe("Reviewed canonical tags. Existing tags should be resolved first; when omitted, deterministic source/topic tags are generated."),
|
|
32265
|
+
related: import_zod35.z.array(import_zod35.z.string()).optional().describe("Reviewed same-vault Library note paths."),
|
|
32266
|
+
relatedVaultNotes: import_zod35.z.array(import_zod35.z.string()).optional().describe("Reviewed cross-vault references in Vault::path.md form."),
|
|
31971
32267
|
localVaultPath: import_zod35.z.string().optional().describe("Filesystem root to also mirror the item to. Optional; falls back to MEMORY_LOCAL_VAULT_ROOT env when set.")
|
|
31972
32268
|
},
|
|
31973
32269
|
output: {
|
|
@@ -31977,6 +32273,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
31977
32273
|
path: import_zod35.z.string().optional().describe("Vault-relative path the item was stored at (under library/...)."),
|
|
31978
32274
|
indexed: import_zod35.z.number().optional().describe("Number of search chunks indexed (0 if embedding failed but the note still saved)."),
|
|
31979
32275
|
dualWritten: import_zod35.z.boolean().optional().describe("True if the item was also mirrored to the local filesystem vault."),
|
|
32276
|
+
nextStep: import_zod35.z.string().optional().describe("Recommended extraction action after the raw Library source is safe."),
|
|
31980
32277
|
code: import_zod35.z.string().optional().describe("Machine-readable denial code when ok is false: quota_exceeded or free_cost_cap."),
|
|
31981
32278
|
error: import_zod35.z.string().optional().describe("Human-readable failure reason when ok is false.")
|
|
31982
32279
|
},
|
|
@@ -32054,10 +32351,27 @@ var init_memory_tool_schemas = __esm({
|
|
|
32054
32351
|
openWorldHint: false
|
|
32055
32352
|
}
|
|
32056
32353
|
};
|
|
32354
|
+
getTool_notePropsSchema = import_zod35.z.object({
|
|
32355
|
+
status: import_zod35.z.string().describe("Status enum value from the target vault contract."),
|
|
32356
|
+
summary: import_zod35.z.string().describe("Short retrieval-ready description."),
|
|
32357
|
+
tags: import_zod35.z.array(import_zod35.z.string()).describe("AI-generated keyword tags, not vault names."),
|
|
32358
|
+
pinned: import_zod35.z.boolean().describe("Recall boost for important notes."),
|
|
32359
|
+
source_type: import_zod35.z.string().describe("Attribution kind: user, person, url, file, channel, thread, or note."),
|
|
32360
|
+
source_ref: import_zod35.z.string().describe("Attribution reference (URL, path, channel, thread, or source note)."),
|
|
32361
|
+
related: import_zod35.z.array(import_zod35.z.string()).describe("Same-vault links (wiki [[ ]] targets)."),
|
|
32362
|
+
related_vault_notes: import_zod35.z.array(import_zod35.z.string()).describe('Cross-vault references in "Vault Name::relative/path.md" form.'),
|
|
32363
|
+
embed: import_zod35.z.boolean().describe("Whether Smart RAG should index the note."),
|
|
32364
|
+
embed_priority: import_zod35.z.enum(["low", "normal", "high"]).describe("Embedding priority."),
|
|
32365
|
+
embedding_summary: import_zod35.z.string().describe("Optional retrieval-specific summary."),
|
|
32366
|
+
type: import_zod35.z.string().describe("Note type from the target vault contract (also used to route the note)."),
|
|
32367
|
+
domain: import_zod35.z.string().describe("Domain folder for Library/Knowledge (AI, SEO, Copywriting & Ads, Business, Spirituality)."),
|
|
32368
|
+
folder: import_zod35.z.string().describe("Explicit sub-folder within the vault; overrides routing-derived folder."),
|
|
32369
|
+
parentMessageId: import_zod35.z.string().describe("Channel messages only: the path of the top-level message this is a reply to. Absent on top-level messages.")
|
|
32370
|
+
}).partial().passthrough();
|
|
32057
32371
|
GetSchema = {
|
|
32058
32372
|
id: "memory-get",
|
|
32059
32373
|
upstreamName: "getTool",
|
|
32060
|
-
description: "Read a single note from a vault by its exact path, or by shareId for a note shared with you and accepted. Returns a revision number \u2014 pass it as baseRevision on a later memory-put/delete-note to detect a concurrent edit instead of silently overwriting it. Requires read scope.",
|
|
32374
|
+
description: "Read a single note from a vault by its exact path, or by shareId for a note shared with you and accepted. Owned notes include their stored Obsidian props so edits can preserve links and template metadata. Returns a revision number \u2014 pass it as baseRevision on a later memory-put/delete-note to detect a concurrent edit instead of silently overwriting it. Requires read scope.",
|
|
32061
32375
|
input: {
|
|
32062
32376
|
vault: import_zod35.z.string().optional().describe(
|
|
32063
32377
|
"Vault to read from. Optional; defaults to the session active vault, then the first vault the caller is entitled to. Ignored when shareId is given."
|
|
@@ -32077,6 +32391,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
32077
32391
|
capturedAt: import_zod35.z.string().describe("ISO-8601 timestamp of when the note was first captured."),
|
|
32078
32392
|
revision: import_zod35.z.number().describe("Current revision number. Pass this as baseRevision when editing, so a concurrent edit by someone else is detected instead of silently overwritten."),
|
|
32079
32393
|
updatedBy: import_zod35.z.string().nullable().describe("Identity that made the last write, if known."),
|
|
32394
|
+
props: getTool_notePropsSchema.optional().describe("Stored Obsidian metadata for an owned note, including links and vault-specific template fields. Omitted for secure or individually shared notes."),
|
|
32080
32395
|
sharedBy: import_zod35.z.string().optional().describe("Present only when read via shareId: the identity who owns and shared this note."),
|
|
32081
32396
|
othersEditing: import_zod35.z.array(import_zod35.z.string()).optional().describe("Advisory only, not a lock: identities who read this same note within the last ~2 minutes and may be about to edit it. Worth a heads-up to the human before you write; the real safety net is still baseRevision on the write itself.")
|
|
32082
32397
|
}).optional().describe("The full note. Present when ok is true."),
|
|
@@ -32124,7 +32439,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
32124
32439
|
openWorldHint: false
|
|
32125
32440
|
}
|
|
32126
32441
|
};
|
|
32127
|
-
|
|
32442
|
+
putTool_notePropsSchema = import_zod35.z.object({
|
|
32128
32443
|
status: import_zod35.z.string().describe("Status enum value from the target vault contract."),
|
|
32129
32444
|
summary: import_zod35.z.string().describe("Short retrieval-ready description."),
|
|
32130
32445
|
tags: import_zod35.z.array(import_zod35.z.string()).describe("AI-generated keyword tags, not vault names."),
|
|
@@ -32140,7 +32455,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
32140
32455
|
domain: import_zod35.z.string().describe("Domain folder for Library/Knowledge (AI, SEO, Copywriting & Ads, Business, Spirituality)."),
|
|
32141
32456
|
folder: import_zod35.z.string().describe("Explicit sub-folder within the vault; overrides routing-derived folder."),
|
|
32142
32457
|
parentMessageId: import_zod35.z.string().describe("Channel messages only: the path of the top-level message this is a reply to. Absent on top-level messages.")
|
|
32143
|
-
}).partial();
|
|
32458
|
+
}).partial().passthrough();
|
|
32144
32459
|
PutSchema = {
|
|
32145
32460
|
id: "memory-put",
|
|
32146
32461
|
upstreamName: "putTool",
|
|
@@ -32153,7 +32468,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
32153
32468
|
shareId: import_zod35.z.string().optional().describe("Edit a note someone individually shared with you and you accepted (accept-share), by its shareId, instead of vault+path. Requires the share to grant edit permission, and baseRevision is mandatory (get the current revision first) since you are editing alongside the owner and possibly others."),
|
|
32154
32469
|
title: import_zod35.z.string().optional().describe("Optional human-readable title; defaults are derived from the path when omitted."),
|
|
32155
32470
|
content: import_zod35.z.string().min(1).describe("The full note body to store and index for semantic search. Must be non-empty."),
|
|
32156
|
-
props:
|
|
32471
|
+
props: putTool_notePropsSchema.optional().describe("Obsidian note primitives plus vault-specific template fields. On edits, supplied fields patch the stored props instead of replacing the whole object; pass an empty array to deliberately clear a link list. Type/domain/folder also steer routing when no vault is given."),
|
|
32157
32472
|
baseRevision: import_zod35.z.number().optional().describe("Revision the edit is based on (from a prior get/put). When provided, the write only applies if the note is still at this revision; otherwise it is rejected as a conflict instead of silently overwriting a concurrent edit. Omit for last-write-wins (fine for solo notes).")
|
|
32158
32473
|
},
|
|
32159
32474
|
output: {
|
|
@@ -32767,6 +33082,51 @@ var init_memory_tool_schemas = __esm({
|
|
|
32767
33082
|
openWorldHint: false
|
|
32768
33083
|
}
|
|
32769
33084
|
};
|
|
33085
|
+
ListTagsSchema = {
|
|
33086
|
+
id: "list-memory-tags",
|
|
33087
|
+
upstreamName: "listTagsTool",
|
|
33088
|
+
description: "List the live canonical tag vocabulary, aliases, usage counts, and per-vault distribution. Use this before choosing tags so existing concepts are reused instead of fragmented.",
|
|
33089
|
+
input: {
|
|
33090
|
+
includeDeprecated: import_zod35.z.boolean().optional()
|
|
33091
|
+
},
|
|
33092
|
+
output: {
|
|
33093
|
+
ok: import_zod35.z.boolean(),
|
|
33094
|
+
tags: import_zod35.z.array(import_zod35.z.object({ tag: import_zod35.z.string(), description: import_zod35.z.string().nullable(), aliases: import_zod35.z.array(import_zod35.z.string()), status: import_zod35.z.enum(["active", "deprecated"]), usageCount: import_zod35.z.number(), vaultUsage: import_zod35.z.record(import_zod35.z.number()) })).optional(),
|
|
33095
|
+
error: import_zod35.z.string().optional()
|
|
33096
|
+
},
|
|
33097
|
+
annotations: { title: "List Memory Tags", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
33098
|
+
};
|
|
33099
|
+
ResolveTagsSchema = {
|
|
33100
|
+
id: "resolve-memory-tags",
|
|
33101
|
+
upstreamName: "resolveTagsTool",
|
|
33102
|
+
description: "Resolve proposed concepts against the live tag vocabulary. Returns reuse, create, or omit. A new tag is allowed only when no equivalent exists and the caller marks the concept central and reusable.",
|
|
33103
|
+
input: {
|
|
33104
|
+
candidates: import_zod35.z.array(import_zod35.z.object({ tag: import_zod35.z.string().min(1), central: import_zod35.z.boolean().optional(), reusable: import_zod35.z.boolean().optional(), description: import_zod35.z.string().optional() })).min(1).max(20)
|
|
33105
|
+
},
|
|
33106
|
+
output: {
|
|
33107
|
+
ok: import_zod35.z.boolean(),
|
|
33108
|
+
resolutions: import_zod35.z.array(import_zod35.z.object({ candidate: import_zod35.z.string(), normalized: import_zod35.z.string(), action: import_zod35.z.enum(["reuse", "create", "omit"]), tag: import_zod35.z.string().optional(), matchedBy: import_zod35.z.enum(["exact", "alias", "near"]).optional(), score: import_zod35.z.number().optional(), reason: import_zod35.z.string() })).optional(),
|
|
33109
|
+
error: import_zod35.z.string().optional()
|
|
33110
|
+
},
|
|
33111
|
+
annotations: { title: "Resolve Memory Tags", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
33112
|
+
};
|
|
33113
|
+
UpsertTagSchema = {
|
|
33114
|
+
id: "upsert-memory-tag",
|
|
33115
|
+
upstreamName: "upsertTagTool",
|
|
33116
|
+
description: "Define or curate one canonical tag, its meaning, aliases, and lifecycle. Use only after resolve-memory-tags returns create, or to merge/deprecate vocabulary intentionally. Requires write scope.",
|
|
33117
|
+
input: {
|
|
33118
|
+
tag: import_zod35.z.string().min(1),
|
|
33119
|
+
description: import_zod35.z.string().optional(),
|
|
33120
|
+
aliases: import_zod35.z.array(import_zod35.z.string()).optional(),
|
|
33121
|
+
status: import_zod35.z.enum(["active", "deprecated"]).optional()
|
|
33122
|
+
},
|
|
33123
|
+
output: {
|
|
33124
|
+
ok: import_zod35.z.boolean(),
|
|
33125
|
+
tag: import_zod35.z.object({ tag: import_zod35.z.string(), description: import_zod35.z.string().nullable(), aliases: import_zod35.z.array(import_zod35.z.string()), status: import_zod35.z.enum(["active", "deprecated"]) }).optional(),
|
|
33126
|
+
error: import_zod35.z.string().optional()
|
|
33127
|
+
},
|
|
33128
|
+
annotations: { title: "Upsert Memory Tag", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
33129
|
+
};
|
|
32770
33130
|
AddVaultSchema = {
|
|
32771
33131
|
id: "add-vault",
|
|
32772
33132
|
upstreamName: "addVaultTool",
|
|
@@ -32834,6 +33194,21 @@ var init_memory_tool_schemas = __esm({
|
|
|
32834
33194
|
openWorldHint: false
|
|
32835
33195
|
}
|
|
32836
33196
|
};
|
|
33197
|
+
GetVaultContractSchema = {
|
|
33198
|
+
id: "get-vault-contract",
|
|
33199
|
+
upstreamName: "getVaultContractTool",
|
|
33200
|
+
description: "Read the machine-enforced purpose, template, statuses, types, natural neighbor vaults, and typed relationship guidance for one of the 13 governed Obsidian-style vaults. Call before composing a note when the correct shape is uncertain.",
|
|
33201
|
+
input: {
|
|
33202
|
+
vault: import_zod35.z.string().describe("One governed vault: Ideas, Inspiration, Knowledge, Library, People, Communications, Calendar, Tasks, Projects, Issues, Improvement Log, Experiments, or Sprint.")
|
|
33203
|
+
},
|
|
33204
|
+
output: {
|
|
33205
|
+
ok: import_zod35.z.boolean(),
|
|
33206
|
+
vault: import_zod35.z.string().optional(),
|
|
33207
|
+
contract: import_zod35.z.record(import_zod35.z.unknown()).optional(),
|
|
33208
|
+
error: import_zod35.z.string().optional()
|
|
33209
|
+
},
|
|
33210
|
+
annotations: { title: "Get Vault Contract", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
33211
|
+
};
|
|
32837
33212
|
ListSharedWithMeSchema = {
|
|
32838
33213
|
id: "list-shared-with-me",
|
|
32839
33214
|
upstreamName: "listSharedWithMeTool",
|
|
@@ -32918,6 +33293,26 @@ var init_memory_tool_schemas = __esm({
|
|
|
32918
33293
|
openWorldHint: false
|
|
32919
33294
|
}
|
|
32920
33295
|
};
|
|
33296
|
+
RouteMemorySchema = {
|
|
33297
|
+
id: "route-memory",
|
|
33298
|
+
upstreamName: "routeMemoryTool",
|
|
33299
|
+
description: "Choose the correct governed vault and folder from content intent. Raw scraped/source material routes to Library; distilled applicable guidance routes to Knowledge. Returns the live vault contract so the result does not depend on prompt memory.",
|
|
33300
|
+
input: {
|
|
33301
|
+
title: import_zod35.z.string().min(1),
|
|
33302
|
+
content: import_zod35.z.string().min(1),
|
|
33303
|
+
type: import_zod35.z.string().optional(),
|
|
33304
|
+
source: import_zod35.z.string().optional()
|
|
33305
|
+
},
|
|
33306
|
+
output: {
|
|
33307
|
+
ok: import_zod35.z.boolean(),
|
|
33308
|
+
vault: import_zod35.z.string().optional(),
|
|
33309
|
+
folder: import_zod35.z.string().optional(),
|
|
33310
|
+
reason: import_zod35.z.string().optional(),
|
|
33311
|
+
contract: import_zod35.z.record(import_zod35.z.unknown()).optional(),
|
|
33312
|
+
error: import_zod35.z.string().optional()
|
|
33313
|
+
},
|
|
33314
|
+
annotations: { title: "Route Memory", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
33315
|
+
};
|
|
32921
33316
|
VideoAnalyzeStartSchema = {
|
|
32922
33317
|
id: "video-analyze-start",
|
|
32923
33318
|
upstreamName: "videoAnalyzeStartTool",
|
|
@@ -33040,7 +33435,10 @@ var init_memory_tool_schemas = __esm({
|
|
|
33040
33435
|
SwapVaultSchema,
|
|
33041
33436
|
SwitchAccountSchema,
|
|
33042
33437
|
UnlinkShareSchema,
|
|
33438
|
+
MemoryCaptureSchema,
|
|
33043
33439
|
MemoryQuestionsSchema,
|
|
33440
|
+
PrepareMemoryWriteSchema,
|
|
33441
|
+
ValidateMemoryWriteSchema,
|
|
33044
33442
|
CreateChannelSchema,
|
|
33045
33443
|
GetMessageNoteSchema,
|
|
33046
33444
|
ListChannelMembersSchema,
|
|
@@ -33053,6 +33451,9 @@ var init_memory_tool_schemas = __esm({
|
|
|
33053
33451
|
ReplyMessageSchema,
|
|
33054
33452
|
FactHistorySchema,
|
|
33055
33453
|
RecordFactSchema,
|
|
33454
|
+
NoteBacklinksSchema,
|
|
33455
|
+
GraphPathSchema,
|
|
33456
|
+
GraphUniverseSchema,
|
|
33056
33457
|
LibraryIngestSchema,
|
|
33057
33458
|
DeleteNoteSchema,
|
|
33058
33459
|
ExportSchema,
|
|
@@ -33082,12 +33483,17 @@ var init_memory_tool_schemas = __esm({
|
|
|
33082
33483
|
InsertTableRowsSchema,
|
|
33083
33484
|
ListTablesSchema,
|
|
33084
33485
|
QueryTableSchema,
|
|
33486
|
+
ListTagsSchema,
|
|
33487
|
+
ResolveTagsSchema,
|
|
33488
|
+
UpsertTagSchema,
|
|
33085
33489
|
AddVaultSchema,
|
|
33086
33490
|
CreateSecureVaultSchema,
|
|
33087
33491
|
DeleteVaultSchema,
|
|
33492
|
+
GetVaultContractSchema,
|
|
33088
33493
|
ListSharedWithMeSchema,
|
|
33089
33494
|
ListVaultsSchema,
|
|
33090
33495
|
ProvisionDefaultsSchema,
|
|
33496
|
+
RouteMemorySchema,
|
|
33091
33497
|
VideoAnalyzeStartSchema,
|
|
33092
33498
|
VideoAnalyzeStatusSchema,
|
|
33093
33499
|
CreateWebhookSchema,
|
|
@@ -33295,8 +33701,44 @@ function registerReadCutovers() {
|
|
|
33295
33701
|
const result = await import_list_webhooks.listWebhooksTool.execute({ ...input, apiKey }, {});
|
|
33296
33702
|
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33297
33703
|
});
|
|
33704
|
+
registerCutover("getVaultContractTool", async (input, apiKey) => {
|
|
33705
|
+
const result = await import_get_vault_contract.getVaultContractTool.execute({ ...input, apiKey }, {});
|
|
33706
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33707
|
+
});
|
|
33708
|
+
registerCutover("routeMemoryTool", async (input, apiKey) => {
|
|
33709
|
+
const result = await import_route_memory.routeMemoryTool.execute({ ...input, apiKey }, {});
|
|
33710
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33711
|
+
});
|
|
33712
|
+
registerCutover("listTagsTool", async (input, apiKey) => {
|
|
33713
|
+
const result = await import_list_tags.listTagsTool.execute({ ...input, apiKey }, {});
|
|
33714
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33715
|
+
});
|
|
33716
|
+
registerCutover("resolveTagsTool", async (input, apiKey) => {
|
|
33717
|
+
const result = await import_resolve_tags.resolveTagsTool.execute({ ...input, apiKey }, {});
|
|
33718
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33719
|
+
});
|
|
33720
|
+
registerCutover("noteBacklinksTool", async (input, apiKey) => {
|
|
33721
|
+
const result = await import_memory_backlinks.noteBacklinksTool.execute({ ...input, apiKey }, {});
|
|
33722
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33723
|
+
});
|
|
33724
|
+
registerCutover("graphUniverseTool", async (input, apiKey) => {
|
|
33725
|
+
const result = await import_memory_graph_universe.graphUniverseTool.execute({ ...input, apiKey }, {});
|
|
33726
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33727
|
+
});
|
|
33728
|
+
registerCutover("graphPathTool", async (input, apiKey) => {
|
|
33729
|
+
const result = await import_memory_graph_path.graphPathTool.execute({ ...input, apiKey }, {});
|
|
33730
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33731
|
+
});
|
|
33732
|
+
registerCutover("prepareMemoryWriteTool", async (input, apiKey) => {
|
|
33733
|
+
const result = await import_prepare_memory_write.prepareMemoryWriteTool.execute({ ...input, apiKey }, {});
|
|
33734
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33735
|
+
});
|
|
33736
|
+
registerCutover("validateMemoryWriteTool", async (input, apiKey) => {
|
|
33737
|
+
const result = await import_validate_memory_write.validateMemoryWriteTool.execute({ ...input, apiKey }, {});
|
|
33738
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33739
|
+
});
|
|
33298
33740
|
}
|
|
33299
|
-
var import_list_approved_senders, import_note_inbox, import_get_message_note, import_list_channel_members, import_my_mentions, import_fact_history, import_export2, import_get, import_list, import_search, import_suggest, import_temporal_recall, import_list_scheduled_actions, import_cost_usage, import_storage_usage, import_table_describe, import_table_list, import_table_query, import_list_shared_with_me, import_list_vaults, import_status, import_list_webhooks, registered;
|
|
33741
|
+
var import_list_approved_senders, import_note_inbox, import_get_message_note, import_list_channel_members, import_my_mentions, import_fact_history, import_export2, import_get, import_list, import_search, import_suggest, import_temporal_recall, import_list_scheduled_actions, import_cost_usage, import_storage_usage, import_table_describe, import_table_list, import_table_query, import_list_shared_with_me, import_list_vaults, import_status, import_list_webhooks, import_get_vault_contract, import_route_memory, import_list_tags, import_resolve_tags, import_memory_backlinks, import_memory_graph_universe, import_memory_graph_path, import_prepare_memory_write, import_validate_memory_write, registered;
|
|
33300
33742
|
var init_reads = __esm({
|
|
33301
33743
|
"src/mcp/memory-cutover/reads.ts"() {
|
|
33302
33744
|
"use strict";
|
|
@@ -33323,6 +33765,15 @@ var init_reads = __esm({
|
|
|
33323
33765
|
import_list_vaults = require("mcpscraper-memory-tools/tools/vaults/list-vaults");
|
|
33324
33766
|
import_status = require("mcpscraper-memory-tools/tools/video/status");
|
|
33325
33767
|
import_list_webhooks = require("mcpscraper-memory-tools/tools/webhooks/list-webhooks");
|
|
33768
|
+
import_get_vault_contract = require("mcpscraper-memory-tools/tools/vaults/get-vault-contract");
|
|
33769
|
+
import_route_memory = require("mcpscraper-memory-tools/tools/vaults/route-memory");
|
|
33770
|
+
import_list_tags = require("mcpscraper-memory-tools/tools/tags/list-tags");
|
|
33771
|
+
import_resolve_tags = require("mcpscraper-memory-tools/tools/tags/resolve-tags");
|
|
33772
|
+
import_memory_backlinks = require("mcpscraper-memory-tools/tools/graph/memory-backlinks");
|
|
33773
|
+
import_memory_graph_universe = require("mcpscraper-memory-tools/tools/graph/memory-graph-universe");
|
|
33774
|
+
import_memory_graph_path = require("mcpscraper-memory-tools/tools/graph/memory-graph-path");
|
|
33775
|
+
import_prepare_memory_write = require("mcpscraper-memory-tools/tools/capture/prepare-memory-write");
|
|
33776
|
+
import_validate_memory_write = require("mcpscraper-memory-tools/tools/capture/validate-memory-write");
|
|
33326
33777
|
registered = false;
|
|
33327
33778
|
}
|
|
33328
33779
|
});
|
|
@@ -33467,8 +33918,16 @@ function registerWriteCutovers() {
|
|
|
33467
33918
|
const result = await import_delete_vault.deleteVaultTool.execute({ ...input, apiKey }, {});
|
|
33468
33919
|
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33469
33920
|
});
|
|
33921
|
+
registerCutover("memoryCaptureTool", async (input, apiKey) => {
|
|
33922
|
+
const result = await import_memory_capture.memoryCaptureTool.execute({ ...input, apiKey }, {});
|
|
33923
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33924
|
+
});
|
|
33925
|
+
registerCutover("upsertTagTool", async (input, apiKey) => {
|
|
33926
|
+
const result = await import_upsert_tag.upsertTagTool.execute({ ...input, apiKey }, {});
|
|
33927
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
33928
|
+
});
|
|
33470
33929
|
}
|
|
33471
|
-
var import_accept_share, import_approve_sender, import_decline_share, import_inbox_settings, import_remove_approved_sender, import_revoke_share, import_set_agent_identity, import_share_note, import_share_vault, import_swap_vault, import_switch_account, import_unlink_share, import_memory_questions, import_create_channel, import_list_channel_messages, import_poll_channel, import_post_message, import_react_message, import_remove_channel_member, import_reply_message, import_record_fact, import_library_ingest, import_delete_note, import_put, import_upload, import_delete_scheduled_action, import_pause_scheduled_action, import_resume_scheduled_action, import_table_create, import_table_delete_rows, import_table_drop, import_table_insert_rows, import_add_vault, import_delete_vault, registered2;
|
|
33930
|
+
var import_accept_share, import_approve_sender, import_decline_share, import_inbox_settings, import_remove_approved_sender, import_revoke_share, import_set_agent_identity, import_share_note, import_share_vault, import_swap_vault, import_switch_account, import_unlink_share, import_memory_questions, import_create_channel, import_list_channel_messages, import_poll_channel, import_post_message, import_react_message, import_remove_channel_member, import_reply_message, import_record_fact, import_library_ingest, import_delete_note, import_put, import_upload, import_delete_scheduled_action, import_pause_scheduled_action, import_resume_scheduled_action, import_table_create, import_table_delete_rows, import_table_drop, import_table_insert_rows, import_add_vault, import_delete_vault, import_memory_capture, import_upsert_tag, registered2;
|
|
33472
33931
|
var init_writes = __esm({
|
|
33473
33932
|
"src/mcp/memory-cutover/writes.ts"() {
|
|
33474
33933
|
"use strict";
|
|
@@ -33507,6 +33966,8 @@ var init_writes = __esm({
|
|
|
33507
33966
|
import_table_insert_rows = require("mcpscraper-memory-tools/tools/tables/table-insert-rows");
|
|
33508
33967
|
import_add_vault = require("mcpscraper-memory-tools/tools/vaults/add-vault");
|
|
33509
33968
|
import_delete_vault = require("mcpscraper-memory-tools/tools/vaults/delete-vault");
|
|
33969
|
+
import_memory_capture = require("mcpscraper-memory-tools/tools/capture/memory-capture");
|
|
33970
|
+
import_upsert_tag = require("mcpscraper-memory-tools/tools/tags/upsert-tag");
|
|
33510
33971
|
registered2 = false;
|
|
33511
33972
|
}
|
|
33512
33973
|
});
|
|
@@ -37811,7 +38272,7 @@ async function depositScrapeToVault(user, opts) {
|
|
|
37811
38272
|
const clipped = content.length > MAX_DEPOSIT_CHARS ? content.slice(0, MAX_DEPOSIT_CHARS) : content;
|
|
37812
38273
|
const { key, error } = await getOrCreateUserMemoryKey(user);
|
|
37813
38274
|
if (!key) return { deposited: false, error: error ?? "memory unavailable" };
|
|
37814
|
-
const vault = opts.vault?.trim() ||
|
|
38275
|
+
const vault = opts.vault?.trim() || "Library";
|
|
37815
38276
|
const title = (opts.title?.trim() || opts.source).slice(0, 200);
|
|
37816
38277
|
const res = await memoryCall(
|
|
37817
38278
|
"libraryIngestTool",
|
|
@@ -37819,7 +38280,7 @@ async function depositScrapeToVault(user, opts) {
|
|
|
37819
38280
|
key
|
|
37820
38281
|
);
|
|
37821
38282
|
if (!res.ok) return { deposited: false, vault, error: res.error ?? "ingest failed" };
|
|
37822
|
-
return { deposited: true, vault, noteId: res.noteId, path: res.path, chunks: res.
|
|
38283
|
+
return { deposited: true, vault, noteId: res.noteId, path: res.path, chunks: res.indexed };
|
|
37823
38284
|
} catch (err) {
|
|
37824
38285
|
return { deposited: false, error: err?.message ?? "deposit failed" };
|
|
37825
38286
|
}
|
|
@@ -37882,16 +38343,16 @@ async function cleanupLocal(cutoff) {
|
|
|
37882
38343
|
let deleted = 0;
|
|
37883
38344
|
let entries;
|
|
37884
38345
|
try {
|
|
37885
|
-
entries = await (0,
|
|
38346
|
+
entries = await (0, import_promises10.readdir)(dir);
|
|
37886
38347
|
} catch {
|
|
37887
38348
|
return { deleted: 0, store: "local" };
|
|
37888
38349
|
}
|
|
37889
38350
|
for (const name of entries) {
|
|
37890
38351
|
const path6 = (0, import_node_path16.join)(dir, name);
|
|
37891
38352
|
try {
|
|
37892
|
-
const s = await (0,
|
|
38353
|
+
const s = await (0, import_promises10.stat)(path6);
|
|
37893
38354
|
if (s.isFile() && s.mtimeMs < cutoff) {
|
|
37894
|
-
await (0,
|
|
38355
|
+
await (0, import_promises10.unlink)(path6);
|
|
37895
38356
|
deleted++;
|
|
37896
38357
|
}
|
|
37897
38358
|
} catch {
|
|
@@ -37908,11 +38369,11 @@ async function cleanupExpiredScrapeBlobs(maxAgeMs = SCRAPE_BLOB_TTL_MS) {
|
|
|
37908
38369
|
return { deleted: 0, store: "none" };
|
|
37909
38370
|
}
|
|
37910
38371
|
}
|
|
37911
|
-
var
|
|
38372
|
+
var import_promises10, import_node_os11, import_node_path16;
|
|
37912
38373
|
var init_scrape_blob_cleanup = __esm({
|
|
37913
38374
|
"src/api/scrape-blob-cleanup.ts"() {
|
|
37914
38375
|
"use strict";
|
|
37915
|
-
|
|
38376
|
+
import_promises10 = require("fs/promises");
|
|
37916
38377
|
import_node_os11 = require("os");
|
|
37917
38378
|
import_node_path16 = require("path");
|
|
37918
38379
|
init_scrape_vault_sink();
|
|
@@ -38231,7 +38692,7 @@ function countPaaQuestions(result) {
|
|
|
38231
38692
|
return Array.isArray(value.flat) ? value.flat.length : 0;
|
|
38232
38693
|
}
|
|
38233
38694
|
function paaCostForQuestionCount(questionCount) {
|
|
38234
|
-
return Math.max(1, questionCount) * MC_COSTS.paa;
|
|
38695
|
+
return MC_COSTS.paa_base + Math.max(1, questionCount) * MC_COSTS.paa;
|
|
38235
38696
|
}
|
|
38236
38697
|
async function processJob(job) {
|
|
38237
38698
|
running++;
|