mcp-scraper 0.44.1 → 0.44.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/bin/api-server.cjs +147 -116
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +17 -25
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/{chunk-TMJVCYDL.js → chunk-2SE4GYCS.js} +18 -26
- package/dist/chunk-2SE4GYCS.js.map +1 -0
- package/dist/chunk-32Z52OE4.js +7 -0
- package/dist/chunk-32Z52OE4.js.map +1 -0
- package/dist/{server-D2Z7BF7S.js → server-JJLFY46K.js} +123 -91
- package/dist/server-JJLFY46K.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2XGU5GVB.js +0 -7
- package/dist/chunk-2XGU5GVB.js.map +0 -1
- package/dist/chunk-TMJVCYDL.js.map +0 -1
- package/dist/server-D2Z7BF7S.js.map +0 -1
package/dist/bin/api-server.cjs
CHANGED
|
@@ -24602,6 +24602,7 @@ function ensureLocalSourcebookSchema() {
|
|
|
24602
24602
|
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
24603
24603
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
24604
24604
|
)`);
|
|
24605
|
+
await publishEligibleEvidenceBackedLocalSourcebookRevisions(db);
|
|
24605
24606
|
})().catch((error) => {
|
|
24606
24607
|
schemaPromise3 = null;
|
|
24607
24608
|
schemaDb3 = null;
|
|
@@ -24609,6 +24610,19 @@ function ensureLocalSourcebookSchema() {
|
|
|
24609
24610
|
});
|
|
24610
24611
|
return schemaPromise3;
|
|
24611
24612
|
}
|
|
24613
|
+
async function publishEligibleEvidenceBackedLocalSourcebookRevisions(db = getDb()) {
|
|
24614
|
+
const result = await db.execute(`UPDATE local_sourcebook_submissions
|
|
24615
|
+
SET status = 'published', published_revision = draft_revision, updated_at = datetime('now')
|
|
24616
|
+
WHERE status = 'needs_review'
|
|
24617
|
+
AND EXISTS (
|
|
24618
|
+
SELECT 1 FROM local_sourcebook_revisions r
|
|
24619
|
+
WHERE r.submission_id = local_sourcebook_submissions.id
|
|
24620
|
+
AND r.revision = local_sourcebook_submissions.draft_revision
|
|
24621
|
+
AND r.actor_kind = 'system'
|
|
24622
|
+
AND r.actor_id = 'local-sourcebook-worker'
|
|
24623
|
+
)`);
|
|
24624
|
+
return Number(result.rowsAffected ?? 0);
|
|
24625
|
+
}
|
|
24612
24626
|
function rowValue(row, key) {
|
|
24613
24627
|
return row[key];
|
|
24614
24628
|
}
|
|
@@ -24678,23 +24692,12 @@ async function getLocalSourcebookDraft(id, ownerUserId) {
|
|
|
24678
24692
|
const result = await getDb().execute({ sql: `SELECT payload_json FROM local_sourcebook_revisions WHERE submission_id = ? AND revision = ?`, args: [id, submission.draftRevision] });
|
|
24679
24693
|
return result.rows[0] ? parseJson2(result.rows[0].payload_json) : null;
|
|
24680
24694
|
}
|
|
24681
|
-
async function reviseLocalSourcebookDraft(id, ownerUserId, payload, baseRevision) {
|
|
24682
|
-
const submission = await getLocalSourcebookSubmission(id, ownerUserId);
|
|
24683
|
-
if (!submission) return null;
|
|
24684
|
-
if (baseRevision !== void 0 && baseRevision !== submission.draftRevision) {
|
|
24685
|
-
throw new Error(`Draft revision conflict: current revision is ${submission.draftRevision}, but the write targeted ${baseRevision}.`);
|
|
24686
|
-
}
|
|
24687
|
-
const revision = submission.draftRevision + 1;
|
|
24688
|
-
await getDb().batch([
|
|
24689
|
-
{ sql: `INSERT INTO local_sourcebook_revisions (submission_id, revision, payload_json, actor_kind, actor_id) VALUES (?, ?, ?, 'owner', ?)`, args: [id, revision, JSON.stringify(payload), String(ownerUserId)] },
|
|
24690
|
-
{ sql: `UPDATE local_sourcebook_submissions SET draft_revision = ?, status = CASE WHEN status = 'published' THEN status ELSE 'needs_review' END, updated_at = datetime('now') WHERE id = ? AND owner_user_id = ?`, args: [revision, id, ownerUserId] }
|
|
24691
|
-
], "write");
|
|
24692
|
-
await event(id, "draft.revised", "owner", String(ownerUserId), { revision });
|
|
24693
|
-
return getLocalSourcebookSubmission(id, ownerUserId);
|
|
24694
|
-
}
|
|
24695
24695
|
async function queueLocalSourcebookRefresh(id, ownerUserId) {
|
|
24696
24696
|
const existing = await getLocalSourcebookSubmission(id, ownerUserId);
|
|
24697
24697
|
if (!existing) return null;
|
|
24698
|
+
if (existing.status === "rejected" || existing.status === "unpublished") {
|
|
24699
|
+
throw new Error(`A ${existing.status} Local Sourcebook listing cannot be refreshed by its owner.`);
|
|
24700
|
+
}
|
|
24698
24701
|
const coverage = { ...existing.coverage, refreshRequestedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
24699
24702
|
await getDb().execute({ sql: `UPDATE local_sourcebook_submissions SET status = 'queued', coverage_json = ?, acquisition_claimed_at = NULL, acquisition_error = NULL, updated_at = datetime('now') WHERE id = ? AND owner_user_id = ?`, args: [JSON.stringify(coverage), id, ownerUserId] });
|
|
24700
24703
|
await event(id, "enrichment.queued", "owner", String(ownerUserId));
|
|
@@ -24732,12 +24735,13 @@ async function completeLocalSourcebookAcquisition(id, payload, coverage, baseRev
|
|
|
24732
24735
|
WHERE EXISTS (SELECT 1 FROM local_sourcebook_submissions WHERE id = ? AND status = 'enriching' AND draft_revision = ?)`,
|
|
24733
24736
|
args: [id, revision, JSON.stringify(payload), id, expectedRevision]
|
|
24734
24737
|
},
|
|
24735
|
-
{ sql: `UPDATE local_sourcebook_submissions SET draft_revision = ?, status = '
|
|
24738
|
+
{ sql: `UPDATE local_sourcebook_submissions SET draft_revision = ?, published_revision = ?, status = 'published', coverage_json = ?, acquisition_claimed_at = NULL, acquisition_error = NULL, updated_at = datetime('now') WHERE id = ? AND status = 'enriching' AND draft_revision = ?`, args: [revision, revision, JSON.stringify(coverage), id, expectedRevision] }
|
|
24736
24739
|
], "write");
|
|
24737
24740
|
if (Number(results[0]?.rowsAffected ?? 0) !== 1 || Number(results[1]?.rowsAffected ?? 0) !== 1) {
|
|
24738
24741
|
throw new Error(`Local Sourcebook acquisition revision conflict: revision ${expectedRevision} changed before completion.`);
|
|
24739
24742
|
}
|
|
24740
24743
|
await event(id, "enrichment.completed", "system", "local-sourcebook-worker", { revision, coverage });
|
|
24744
|
+
await event(id, "publication.auto_published", "system", "local-sourcebook-worker", { revision });
|
|
24741
24745
|
return getLocalSourcebookSubmission(id);
|
|
24742
24746
|
}
|
|
24743
24747
|
async function failLocalSourcebookAcquisition(id, message) {
|
|
@@ -24760,6 +24764,15 @@ async function listQueuedLocalSourcebookSubmissionIds(limit = 25) {
|
|
|
24760
24764
|
async function publishLocalSourcebookSubmission(id) {
|
|
24761
24765
|
const submission = await getLocalSourcebookSubmission(id);
|
|
24762
24766
|
if (!submission) return null;
|
|
24767
|
+
const revision = await getDb().execute({
|
|
24768
|
+
sql: `SELECT actor_kind, actor_id FROM local_sourcebook_revisions WHERE submission_id = ? AND revision = ? LIMIT 1`,
|
|
24769
|
+
args: [id, submission.draftRevision]
|
|
24770
|
+
});
|
|
24771
|
+
const actorKind = revision.rows[0] ? String(revision.rows[0].actor_kind) : "";
|
|
24772
|
+
const actorId = revision.rows[0] ? String(revision.rows[0].actor_id) : "";
|
|
24773
|
+
if (actorKind !== "system" || actorId !== "local-sourcebook-worker") {
|
|
24774
|
+
throw new Error("Only a system-compiled Local Sourcebook revision can be published.");
|
|
24775
|
+
}
|
|
24763
24776
|
await getDb().execute({ sql: `UPDATE local_sourcebook_submissions SET status = 'published', published_revision = draft_revision, updated_at = datetime('now') WHERE id = ?`, args: [id] });
|
|
24764
24777
|
await event(id, "publication.published", "admin", "admin", { revision: submission.draftRevision });
|
|
24765
24778
|
return getLocalSourcebookSubmission(id);
|
|
@@ -24776,6 +24789,14 @@ async function listPublicLocalSourcebook(category, state) {
|
|
|
24776
24789
|
const result = await getDb().execute({ sql: `SELECT r.payload_json FROM local_sourcebook_submissions s JOIN local_sourcebook_revisions r ON r.submission_id = s.id AND r.revision = s.published_revision WHERE s.category = ? AND s.state = ? AND s.published_revision IS NOT NULL AND s.status NOT IN ('unpublished', 'rejected') ORDER BY s.business_name`, args: [category, state] });
|
|
24777
24790
|
return result.rows.map((row) => parseJson2(row.payload_json));
|
|
24778
24791
|
}
|
|
24792
|
+
async function listAllPublicLocalSourcebook(category) {
|
|
24793
|
+
await ensureLocalSourcebookSchema();
|
|
24794
|
+
const result = category ? await getDb().execute({
|
|
24795
|
+
sql: `SELECT r.payload_json FROM local_sourcebook_submissions s JOIN local_sourcebook_revisions r ON r.submission_id = s.id AND r.revision = s.published_revision WHERE s.category = ? AND s.published_revision IS NOT NULL AND s.status NOT IN ('unpublished', 'rejected') ORDER BY s.state, s.business_name`,
|
|
24796
|
+
args: [category]
|
|
24797
|
+
}) : await getDb().execute(`SELECT r.payload_json FROM local_sourcebook_submissions s JOIN local_sourcebook_revisions r ON r.submission_id = s.id AND r.revision = s.published_revision WHERE s.published_revision IS NOT NULL AND s.status NOT IN ('unpublished', 'rejected') ORDER BY s.category, s.state, s.business_name`);
|
|
24798
|
+
return result.rows.map((row) => parseJson2(row.payload_json));
|
|
24799
|
+
}
|
|
24779
24800
|
async function getPublicLocalSourcebook(category, state, slug2) {
|
|
24780
24801
|
await ensureLocalSourcebookSchema();
|
|
24781
24802
|
const result = await getDb().execute({ sql: `SELECT r.payload_json FROM local_sourcebook_submissions s JOIN local_sourcebook_revisions r ON r.submission_id = s.id AND r.revision = s.published_revision WHERE s.category = ? AND s.state = ? AND s.slug = ? AND s.published_revision IS NOT NULL AND s.status NOT IN ('unpublished', 'rejected') LIMIT 1`, args: [category, state, slug2] });
|
|
@@ -25431,6 +25452,41 @@ var init_MapsExtractor = __esm({
|
|
|
25431
25452
|
}
|
|
25432
25453
|
});
|
|
25433
25454
|
|
|
25455
|
+
// src/api/local-sourcebook-public-urls.ts
|
|
25456
|
+
function rootDomain() {
|
|
25457
|
+
const configured = process.env.LOCAL_SOURCEBOOK_PUBLIC_ROOT_DOMAIN?.trim() || DEFAULT_ROOT_DOMAIN;
|
|
25458
|
+
return configured.replace(/^https?:\/\//i, "").replace(/^www\./i, "").replace(/\/.*$/, "").replace(/\.+$/, "").toLowerCase();
|
|
25459
|
+
}
|
|
25460
|
+
function localSourcebookPublicUrls(category, state, slug2) {
|
|
25461
|
+
const categoryUrl = `https://${category}.${rootDomain()}`;
|
|
25462
|
+
const statePath = `/${state.toLowerCase()}`;
|
|
25463
|
+
const profilePath = `${statePath}/${slug2}/`;
|
|
25464
|
+
const reviewsPath = `${statePath}/${slug2}/reviews`;
|
|
25465
|
+
return {
|
|
25466
|
+
categoryUrl,
|
|
25467
|
+
nationwideDirectoryUrl: `${categoryUrl}/directory`,
|
|
25468
|
+
stateUrl: `${categoryUrl}${statePath}`,
|
|
25469
|
+
profileUrl: `${categoryUrl}${profilePath}`,
|
|
25470
|
+
reviewsUrl: `${categoryUrl}${reviewsPath}`,
|
|
25471
|
+
profilePath,
|
|
25472
|
+
reviewsPath
|
|
25473
|
+
};
|
|
25474
|
+
}
|
|
25475
|
+
function localSourcebookPublicationLinks(submission) {
|
|
25476
|
+
return {
|
|
25477
|
+
...localSourcebookPublicUrls(submission.category, submission.state, submission.slug),
|
|
25478
|
+
publicationStatus: submission.status,
|
|
25479
|
+
isLive: submission.status === "published" && submission.publishedRevision !== null
|
|
25480
|
+
};
|
|
25481
|
+
}
|
|
25482
|
+
var DEFAULT_ROOT_DOMAIN;
|
|
25483
|
+
var init_local_sourcebook_public_urls = __esm({
|
|
25484
|
+
"src/api/local-sourcebook-public-urls.ts"() {
|
|
25485
|
+
"use strict";
|
|
25486
|
+
DEFAULT_ROOT_DOMAIN = "localsourcebook.com";
|
|
25487
|
+
}
|
|
25488
|
+
});
|
|
25489
|
+
|
|
25434
25490
|
// src/api/local-sourcebook-compiler.ts
|
|
25435
25491
|
function digest(value) {
|
|
25436
25492
|
return (0, import_node_crypto13.createHash)("sha256").update(value).digest("hex").slice(0, 20);
|
|
@@ -25706,6 +25762,7 @@ function compileLocalSourcebookListing(input) {
|
|
|
25706
25762
|
evidenceIds: mapsEvidenceId ? [mapsEvidenceId] : []
|
|
25707
25763
|
}
|
|
25708
25764
|
];
|
|
25765
|
+
const publicUrls = localSourcebookPublicUrls(input.submission.category, input.submission.state, input.submission.slug);
|
|
25709
25766
|
const listing = {
|
|
25710
25767
|
id: input.submission.id,
|
|
25711
25768
|
publicationRevision: input.submission.draftRevision + 1,
|
|
@@ -25714,6 +25771,14 @@ function compileLocalSourcebookListing(input) {
|
|
|
25714
25771
|
state: input.submission.state.toLowerCase(),
|
|
25715
25772
|
stateName: STATE_NAMES[input.submission.state.toUpperCase()] ?? input.submission.state.toUpperCase(),
|
|
25716
25773
|
slug: input.submission.slug,
|
|
25774
|
+
canonicalPaths: {
|
|
25775
|
+
profile: publicUrls.profilePath,
|
|
25776
|
+
reviews: publicUrls.reviewsPath
|
|
25777
|
+
},
|
|
25778
|
+
canonicalUrls: {
|
|
25779
|
+
profile: publicUrls.profileUrl,
|
|
25780
|
+
reviews: publicUrls.reviewsUrl
|
|
25781
|
+
},
|
|
25717
25782
|
name: maps?.name || input.submission.businessName,
|
|
25718
25783
|
summary,
|
|
25719
25784
|
description,
|
|
@@ -25777,6 +25842,7 @@ var init_local_sourcebook_compiler = __esm({
|
|
|
25777
25842
|
"src/api/local-sourcebook-compiler.ts"() {
|
|
25778
25843
|
"use strict";
|
|
25779
25844
|
import_node_crypto13 = require("crypto");
|
|
25845
|
+
init_local_sourcebook_public_urls();
|
|
25780
25846
|
CATEGORY_LABELS = {
|
|
25781
25847
|
home: "Home & property services",
|
|
25782
25848
|
professional: "Professional services",
|
|
@@ -26016,11 +26082,12 @@ async function runLocalSourcebookAcquisition(submission, provider = createDefaul
|
|
|
26016
26082
|
await logRequestEvent({ userId: submission.ownerUserId, source: "local_sourcebook_maps", status: "done", query: submission.businessName, location: submission.state.toUpperCase(), resultCount: maps.reviews.length, result: { submissionId: submission.id, placeUrl: maps.placeUrl, cid: maps.cidDecimal ?? maps.cid, reviewsStatus: maps.reviewsStatus, reviewsRetained: maps.reviews.length, services: maps.services.length, areasServed: maps.areasServed.length } });
|
|
26017
26083
|
} catch (error) {
|
|
26018
26084
|
mapsError = errorMessage2(error);
|
|
26085
|
+
maps = null;
|
|
26019
26086
|
await creditMcIdempotent(submission.ownerUserId, MC_COSTS.maps_place, LedgerOperation.REFUND, `Local Sourcebook failed exact-place acquisition: ${submission.id}`, `${billingCycle}:maps-failure-refund`);
|
|
26020
26087
|
mapsRefunded = true;
|
|
26021
26088
|
await logRequestEvent({ userId: submission.ownerUserId, source: "local_sourcebook_maps", status: "failed", query: submission.businessName, location: submission.state.toUpperCase(), error: mapsError });
|
|
26022
26089
|
}
|
|
26023
|
-
if (!
|
|
26090
|
+
if (!maps) throw new Error(`Exact-place acquisition is required before publication. Maps: ${mapsError || "not available"}. Website: ${siteError || (site ? "captured" : "not available")}.`);
|
|
26024
26091
|
const compiled = compileLocalSourcebookListing({
|
|
26025
26092
|
submission,
|
|
26026
26093
|
site,
|
|
@@ -36602,18 +36669,22 @@ async function resolveLocalSourcebookTags(candidates) {
|
|
|
36602
36669
|
function getLocalSourcebookContract(category) {
|
|
36603
36670
|
return {
|
|
36604
36671
|
name: "Local Sourcebook listing",
|
|
36605
|
-
version: "
|
|
36672
|
+
version: "local_sourcebook_listing_v2",
|
|
36606
36673
|
purpose: "An owner-scoped, evidence-backed local business record with a separate public profile and complete captured-review archive.",
|
|
36607
36674
|
categories: LOCAL_SOURCEBOOK_CATEGORIES,
|
|
36608
36675
|
selectedCategory: category ?? null,
|
|
36609
36676
|
categoryTag: category ? CATEGORY_TAG[category] : null,
|
|
36610
|
-
canonicalRoutes: {
|
|
36677
|
+
canonicalRoutes: {
|
|
36678
|
+
nationwideDirectory: "https://{category}.localsourcebook.com/directory",
|
|
36679
|
+
profile: "https://{category}.localsourcebook.com/{state}/{business-slug}/",
|
|
36680
|
+
reviews: "https://{category}.localsourcebook.com/{state}/{business-slug}/reviews"
|
|
36681
|
+
},
|
|
36611
36682
|
requiredCreateFields: ["category", "state", "businessName", "websiteUrl", "tags", "idempotencyKey"],
|
|
36612
|
-
|
|
36683
|
+
systemCompiledSections: ["identity", "services/products", "service areas/locations", "genuine media", "reviews and theme counts", "evidence", "answered FAQ", "collection receipts"],
|
|
36613
36684
|
workflow: ["list-local-sourcebook-tags", "get-local-sourcebook-contract", "prepare-local-sourcebook-write", "validate-local-sourcebook-write", "local-sourcebook-capture", "local_sourcebook_submission_status"],
|
|
36614
|
-
ownership: "Only the MCP Scraper account that captures a listing can read or
|
|
36685
|
+
ownership: "Only the MCP Scraper account that captures a listing can read it or request a paid evidence refresh.",
|
|
36615
36686
|
acquisition: { websitePagesMaximum: 100, reviewsMaximum: 500, exactMapsIdentityRequired: true, partialResultsRequireStoppingReasons: true },
|
|
36616
|
-
publication: { automatic: false, adminReviewRequired:
|
|
36687
|
+
publication: { automatic: true, evidenceCompiledOnly: true, ownerAuthoredClaimsAccepted: false, adminReviewRequired: false, lastPublishedRevisionRemainsPublicDuringRefresh: true },
|
|
36617
36688
|
tagPolicy: { inspectVocabularyFirst: true, minimum: 1, maximum: 20, newTagsRequire: ["central=true", "reusable=true", "description"], newTagsStartAs: "pending" }
|
|
36618
36689
|
};
|
|
36619
36690
|
}
|
|
@@ -36627,16 +36698,18 @@ async function prepareLocalSourcebookWrite(input) {
|
|
|
36627
36698
|
...parsed.tags.filter((tag) => tag !== categoryTag).map((tag) => ({ tag }))
|
|
36628
36699
|
];
|
|
36629
36700
|
const tagResolutions = await resolveLocalSourcebookTags(candidates);
|
|
36701
|
+
const publicUrls = localSourcebookPublicUrls(parsed.category, parsed.state, slug2);
|
|
36630
36702
|
return {
|
|
36631
36703
|
ok: true,
|
|
36632
|
-
route: { category: parsed.category, state: parsed.state, slug: slug2,
|
|
36704
|
+
route: { category: parsed.category, state: parsed.state, slug: slug2, ...publicUrls },
|
|
36633
36705
|
proposedWrite: { ...parsed, slug: slug2, tags: tagResolutions.filter((item) => item.action === "reuse").map((item) => item.tag) },
|
|
36634
36706
|
contract: getLocalSourcebookContract(parsed.category),
|
|
36635
36707
|
tagResolutions,
|
|
36636
36708
|
instructions: [
|
|
36637
36709
|
"Resolve every review candidate before capture; do not silently create a near-duplicate tag.",
|
|
36638
36710
|
"Call validate-local-sourcebook-write with the proposed identity, resolved tags, and any required tag decisions.",
|
|
36639
|
-
"Call local-sourcebook-capture only after validation returns valid=true. Capture
|
|
36711
|
+
"Call local-sourcebook-capture only after validation returns valid=true. Capture queues paid acquisition and automatically publishes the resulting system-compiled evidence revision.",
|
|
36712
|
+
"Owners cannot supply public listing claims directly. Request local_sourcebook_refresh when source-backed public facts need to be reacquired."
|
|
36640
36713
|
]
|
|
36641
36714
|
};
|
|
36642
36715
|
}
|
|
@@ -36644,17 +36717,9 @@ async function validateLocalSourcebookWrite(input) {
|
|
|
36644
36717
|
const errors = [];
|
|
36645
36718
|
const warnings = [];
|
|
36646
36719
|
let normalizedIdentity2;
|
|
36647
|
-
|
|
36648
|
-
if (
|
|
36649
|
-
|
|
36650
|
-
const parsedListing = DirectoryListingDraftSchema.safeParse(input.listing);
|
|
36651
|
-
if (!parsedListing.success) errors.push(...parsedListing.error.issues.map((issue) => `listing.${issue.path.join(".")}: ${issue.message}`));
|
|
36652
|
-
else normalizedListing = parsedListing.data;
|
|
36653
|
-
} else {
|
|
36654
|
-
const parsedIdentity = DirectoryIdentitySchema.safeParse(input.identity);
|
|
36655
|
-
if (!parsedIdentity.success) errors.push(...parsedIdentity.error.issues.map((issue) => `identity.${issue.path.join(".")}: ${issue.message}`));
|
|
36656
|
-
else normalizedIdentity2 = parsedIdentity.data;
|
|
36657
|
-
}
|
|
36720
|
+
const parsedIdentity = DirectoryIdentitySchema.safeParse(input.identity);
|
|
36721
|
+
if (!parsedIdentity.success) errors.push(...parsedIdentity.error.issues.map((issue) => `identity.${issue.path.join(".")}: ${issue.message}`));
|
|
36722
|
+
else normalizedIdentity2 = parsedIdentity.data;
|
|
36658
36723
|
const candidates = input.tagCandidates ?? (normalizedIdentity2?.tags.map((tag) => ({ tag })) ?? []);
|
|
36659
36724
|
const resolutions = await resolveLocalSourcebookTags(candidates);
|
|
36660
36725
|
const decisions = new Map((input.tagDecisions ?? []).map((decision) => [normalizeTag(decision.tag), decision]));
|
|
@@ -36673,12 +36738,12 @@ async function validateLocalSourcebookWrite(input) {
|
|
|
36673
36738
|
}
|
|
36674
36739
|
if (resolution2.action === "omit") warnings.push(`Tag \u201C${resolution2.candidate}\u201D will be omitted: ${resolution2.reason}`);
|
|
36675
36740
|
}
|
|
36676
|
-
if (
|
|
36741
|
+
if (normalizedIdentity2) {
|
|
36677
36742
|
const categoryTag = CATEGORY_TAG[normalizedIdentity2.category];
|
|
36678
36743
|
if (!normalizedTags.includes(categoryTag)) normalizedTags.unshift(categoryTag);
|
|
36679
36744
|
}
|
|
36680
36745
|
if (!normalizedTags.length) errors.push("At least one canonical directory tag is required.");
|
|
36681
|
-
return { ok: true, valid: errors.length === 0, errors, warnings, normalizedIdentity: normalizedIdentity2,
|
|
36746
|
+
return { ok: true, valid: errors.length === 0, errors, warnings, normalizedIdentity: normalizedIdentity2, normalizedTags: [...new Set(normalizedTags)], tagResolutions: resolutions };
|
|
36682
36747
|
}
|
|
36683
36748
|
async function persistLocalSourcebookTags(submissionId, userId, tags, decisions = []) {
|
|
36684
36749
|
await ensureLocalSourcebookTags();
|
|
@@ -36695,18 +36760,14 @@ async function persistLocalSourcebookTags(submissionId, userId, tags, decisions
|
|
|
36695
36760
|
await db.execute({ sql: `INSERT OR IGNORE INTO local_sourcebook_submission_tags (submission_id, tag) VALUES (?, ?)`, args: [submissionId, tag] });
|
|
36696
36761
|
}
|
|
36697
36762
|
}
|
|
36698
|
-
|
|
36699
|
-
await ensureLocalSourcebookTags();
|
|
36700
|
-
await getDb().execute({ sql: `DELETE FROM local_sourcebook_submission_tags WHERE submission_id = ?`, args: [submissionId] });
|
|
36701
|
-
await persistLocalSourcebookTags(submissionId, userId, tags, decisions);
|
|
36702
|
-
}
|
|
36703
|
-
var import_zod29, DIRECTORY_TAG_SEEDS, CATEGORY_TAG, DirectoryTagCandidateSchema, DirectoryTagDecisionSchema, DirectoryIdentitySchema, DirectoryListingDraftSchema;
|
|
36763
|
+
var import_zod29, DIRECTORY_TAG_SEEDS, CATEGORY_TAG, DirectoryTagCandidateSchema, DirectoryTagDecisionSchema, DirectoryIdentitySchema;
|
|
36704
36764
|
var init_local_sourcebook_governance = __esm({
|
|
36705
36765
|
"src/api/local-sourcebook-governance.ts"() {
|
|
36706
36766
|
"use strict";
|
|
36707
36767
|
import_zod29 = require("zod");
|
|
36708
36768
|
init_db();
|
|
36709
36769
|
init_local_sourcebook_repository();
|
|
36770
|
+
init_local_sourcebook_public_urls();
|
|
36710
36771
|
DIRECTORY_TAG_SEEDS = [
|
|
36711
36772
|
{ tag: "home-services", description: "Businesses that maintain, repair, improve, or protect homes and property.", aliases: ["home service", "home and property services"] },
|
|
36712
36773
|
{ tag: "professional-services", description: "Local professional and business service providers.", aliases: ["professional service"] },
|
|
@@ -36753,23 +36814,6 @@ var init_local_sourcebook_governance = __esm({
|
|
|
36753
36814
|
tags: import_zod29.z.array(import_zod29.z.string().trim().min(1).max(60)).max(20).default([]),
|
|
36754
36815
|
idempotencyKey: import_zod29.z.string().trim().min(8).max(200)
|
|
36755
36816
|
});
|
|
36756
|
-
DirectoryListingDraftSchema = import_zod29.z.object({
|
|
36757
|
-
id: import_zod29.z.string().min(1),
|
|
36758
|
-
category: import_zod29.z.enum(LOCAL_SOURCEBOOK_CATEGORIES),
|
|
36759
|
-
state: import_zod29.z.string().trim().length(2),
|
|
36760
|
-
slug: import_zod29.z.string().trim().min(1),
|
|
36761
|
-
name: import_zod29.z.string().trim().min(2),
|
|
36762
|
-
summary: import_zod29.z.string().trim().min(20),
|
|
36763
|
-
description: import_zod29.z.string().trim().min(20),
|
|
36764
|
-
website: import_zod29.z.url(),
|
|
36765
|
-
services: import_zod29.z.array(import_zod29.z.string()),
|
|
36766
|
-
products: import_zod29.z.array(import_zod29.z.string()),
|
|
36767
|
-
serviceAreas: import_zod29.z.array(import_zod29.z.string()),
|
|
36768
|
-
media: import_zod29.z.array(import_zod29.z.record(import_zod29.z.string(), import_zod29.z.unknown())),
|
|
36769
|
-
reviews: import_zod29.z.array(import_zod29.z.record(import_zod29.z.string(), import_zod29.z.unknown())),
|
|
36770
|
-
evidence: import_zod29.z.array(import_zod29.z.record(import_zod29.z.string(), import_zod29.z.unknown())),
|
|
36771
|
-
faq: import_zod29.z.array(import_zod29.z.object({ question: import_zod29.z.string().min(3), answer: import_zod29.z.string().min(12), evidenceIds: import_zod29.z.array(import_zod29.z.string()) }))
|
|
36772
|
-
}).passthrough();
|
|
36773
36817
|
}
|
|
36774
36818
|
});
|
|
36775
36819
|
|
|
@@ -36779,10 +36823,10 @@ function acquisitionPlan(websiteUrl) {
|
|
|
36779
36823
|
website: { startUrl: websiteUrl, mode: "broad_site_crawl", capture: ["homepage", "services", "products", "locations", "service_areas", "about", "team_staff", "contact", "policies"] },
|
|
36780
36824
|
media: { requirement: "genuine_business_images_only", sources: ["business_website", "business_team_pages", "verified_business_profiles"] },
|
|
36781
36825
|
reviews: { mode: "exhaust_accessible_continuation", requirement: "retain_each_review_and_source", disclosure: "report captured count, reported available count, and exact stopping reason" },
|
|
36782
|
-
publication: { automatic:
|
|
36826
|
+
publication: { automatic: true, evidenceCompiledOnly: true, adminReviewRequired: false }
|
|
36783
36827
|
};
|
|
36784
36828
|
}
|
|
36785
|
-
var import_hono17, import_zod30, slug, SubmitSchema,
|
|
36829
|
+
var import_hono17, import_zod30, slug, SubmitSchema, PrepareWriteSchema, ValidateWriteSchema, CaptureWriteSchema, localSourcebookApp, publicLocalSourcebookApp, adminLocalSourcebookApp;
|
|
36786
36830
|
var init_local_sourcebook_routes = __esm({
|
|
36787
36831
|
"src/api/local-sourcebook-routes.ts"() {
|
|
36788
36832
|
"use strict";
|
|
@@ -36793,6 +36837,7 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36793
36837
|
init_local_sourcebook_dispatch();
|
|
36794
36838
|
init_local_sourcebook_governance();
|
|
36795
36839
|
init_local_sourcebook_repository();
|
|
36840
|
+
init_local_sourcebook_public_urls();
|
|
36796
36841
|
slug = (value) => value.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 100);
|
|
36797
36842
|
SubmitSchema = import_zod30.z.object({
|
|
36798
36843
|
category: import_zod30.z.enum(LOCAL_SOURCEBOOK_CATEGORIES),
|
|
@@ -36802,13 +36847,9 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36802
36847
|
slug: import_zod30.z.string().trim().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(100).optional(),
|
|
36803
36848
|
idempotencyKey: import_zod30.z.string().trim().min(8).max(200).optional()
|
|
36804
36849
|
}).strict();
|
|
36805
|
-
DraftSchema = import_zod30.z.object({ payload: import_zod30.z.record(import_zod30.z.string(), import_zod30.z.unknown()) }).strict();
|
|
36806
36850
|
PrepareWriteSchema = DirectoryIdentitySchema.extend({ tagCandidates: import_zod30.z.array(DirectoryTagCandidateSchema).max(20).optional() });
|
|
36807
36851
|
ValidateWriteSchema = import_zod30.z.object({
|
|
36808
36852
|
identity: DirectoryIdentitySchema.optional(),
|
|
36809
|
-
listing: import_zod30.z.record(import_zod30.z.string(), import_zod30.z.unknown()).optional(),
|
|
36810
|
-
submissionId: import_zod30.z.string().trim().min(1).optional(),
|
|
36811
|
-
baseRevision: import_zod30.z.number().int().min(1).optional(),
|
|
36812
36853
|
tagCandidates: import_zod30.z.array(DirectoryTagCandidateSchema).max(20).optional(),
|
|
36813
36854
|
tagDecisions: import_zod30.z.array(DirectoryTagDecisionSchema).max(20).optional()
|
|
36814
36855
|
}).strict();
|
|
@@ -36840,18 +36881,12 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36840
36881
|
const validation = await validateLocalSourcebookWrite(parsed.data);
|
|
36841
36882
|
if (!validation.valid) return c.json({ error: "invalid_directory_write", ...validation }, 400);
|
|
36842
36883
|
try {
|
|
36843
|
-
if (parsed.data.submissionId) {
|
|
36844
|
-
const submission2 = await getLocalSourcebookSubmission(parsed.data.submissionId, Number(user.id));
|
|
36845
|
-
if (!submission2) return c.json({ error: "not_found" }, 404);
|
|
36846
|
-
const updated = await reviseLocalSourcebookDraft(submission2.id, Number(user.id), validation.normalizedListing, parsed.data.baseRevision);
|
|
36847
|
-
await replaceLocalSourcebookTags(submission2.id, Number(user.id), validation.normalizedTags, parsed.data.tagDecisions);
|
|
36848
|
-
return c.json({ ok: true, valid: true, submission: updated, normalizedTags: validation.normalizedTags, captured: "draft_revision", acquisitionQueued: false });
|
|
36849
|
-
}
|
|
36850
36884
|
const identity = validation.normalizedIdentity;
|
|
36851
36885
|
if (!parsed.data.idempotencyKey && !identity.idempotencyKey) {
|
|
36852
36886
|
return c.json({ error: "idempotency_key_required", message: "A stable idempotencyKey is required for a new Local Sourcebook capture." }, 400);
|
|
36853
36887
|
}
|
|
36854
36888
|
const listingSlug = identity.slug ?? slug(identity.businessName);
|
|
36889
|
+
const publicUrls = localSourcebookPublicUrls(identity.category, identity.state, listingSlug);
|
|
36855
36890
|
const submission = await createLocalSourcebookSubmission({
|
|
36856
36891
|
ownerUserId: Number(user.id),
|
|
36857
36892
|
category: identity.category,
|
|
@@ -36868,7 +36903,8 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36868
36903
|
name: identity.businessName,
|
|
36869
36904
|
websiteUrl: identity.websiteUrl,
|
|
36870
36905
|
tags: validation.normalizedTags,
|
|
36871
|
-
canonicalPaths: { profile:
|
|
36906
|
+
canonicalPaths: { profile: publicUrls.profilePath, reviews: publicUrls.reviewsPath },
|
|
36907
|
+
canonicalUrls: { profile: publicUrls.profileUrl, reviews: publicUrls.reviewsUrl },
|
|
36872
36908
|
verificationState: "submitted",
|
|
36873
36909
|
acquisitionPlan: acquisitionPlan(identity.websiteUrl),
|
|
36874
36910
|
evidence: [],
|
|
@@ -36878,7 +36914,7 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36878
36914
|
});
|
|
36879
36915
|
await persistLocalSourcebookTags(submission.id, Number(user.id), validation.normalizedTags, parsed.data.tagDecisions);
|
|
36880
36916
|
const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
|
|
36881
|
-
return c.json({ ok: true, valid: true, submission, normalizedTags: validation.normalizedTags, acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(identity.websiteUrl) }, 202);
|
|
36917
|
+
return c.json({ ok: true, valid: true, submission, publicUrls: localSourcebookPublicationLinks(submission), normalizedTags: validation.normalizedTags, acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(identity.websiteUrl) }, 202);
|
|
36882
36918
|
} catch (error) {
|
|
36883
36919
|
const message = error instanceof Error ? error.message : String(error);
|
|
36884
36920
|
const conflict = message.includes("revision conflict") ? "revision_conflict" : message.includes("idempotency key conflicts") ? "idempotency_conflict" : null;
|
|
@@ -36892,6 +36928,7 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36892
36928
|
if (!parsed.success) return c.json({ error: "invalid_submission", issues: parsed.error.issues }, 400);
|
|
36893
36929
|
const input = parsed.data;
|
|
36894
36930
|
const listingSlug = input.slug ?? slug(input.businessName);
|
|
36931
|
+
const publicUrls = localSourcebookPublicUrls(input.category, input.state, listingSlug);
|
|
36895
36932
|
try {
|
|
36896
36933
|
const submission = await createLocalSourcebookSubmission({
|
|
36897
36934
|
ownerUserId: Number(user.id),
|
|
@@ -36904,7 +36941,8 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36904
36941
|
slug: listingSlug,
|
|
36905
36942
|
name: input.businessName,
|
|
36906
36943
|
websiteUrl: input.websiteUrl,
|
|
36907
|
-
canonicalPaths: { profile:
|
|
36944
|
+
canonicalPaths: { profile: publicUrls.profilePath, reviews: publicUrls.reviewsPath },
|
|
36945
|
+
canonicalUrls: { profile: publicUrls.profileUrl, reviews: publicUrls.reviewsUrl },
|
|
36908
36946
|
verificationState: "submitted",
|
|
36909
36947
|
acquisitionPlan: acquisitionPlan(input.websiteUrl),
|
|
36910
36948
|
evidence: [],
|
|
@@ -36913,7 +36951,7 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36913
36951
|
}
|
|
36914
36952
|
});
|
|
36915
36953
|
const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
|
|
36916
|
-
return c.json({ ok: true, submission, acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(input.websiteUrl) }, 202);
|
|
36954
|
+
return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(input.websiteUrl) }, 202);
|
|
36917
36955
|
} catch (error) {
|
|
36918
36956
|
return c.json({ error: "submission_conflict", message: error instanceof Error ? error.message : String(error) }, 409);
|
|
36919
36957
|
}
|
|
@@ -36922,26 +36960,27 @@ var init_local_sourcebook_routes = __esm({
|
|
|
36922
36960
|
const userId = Number(c.get("user").id);
|
|
36923
36961
|
const submission = await getLocalSourcebookSubmission(c.req.param("id"), userId);
|
|
36924
36962
|
if (!submission) return c.json({ error: "not_found" }, 404);
|
|
36925
|
-
return c.json({ ok: true, submission, draft: await getLocalSourcebookDraft(submission.id, userId) });
|
|
36926
|
-
});
|
|
36927
|
-
localSourcebookApp.on(["PATCH", "POST"], "/submissions/:id/draft", createApiKeyAuth(), async (c) => {
|
|
36928
|
-
const user = c.get("user");
|
|
36929
|
-
if (!user.subscription_tier) return c.json({ error: "subscription_required" }, 402);
|
|
36930
|
-
const parsed = DraftSchema.safeParse(await c.req.json().catch(() => null));
|
|
36931
|
-
if (!parsed.success) return c.json({ error: "invalid_draft", issues: parsed.error.issues }, 400);
|
|
36932
|
-
const submission = await reviseLocalSourcebookDraft(c.req.param("id"), Number(user.id), parsed.data.payload);
|
|
36933
|
-
if (!submission) return c.json({ error: "not_found" }, 404);
|
|
36934
|
-
return c.json({ ok: true, submission });
|
|
36963
|
+
return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), draft: await getLocalSourcebookDraft(submission.id, userId) });
|
|
36935
36964
|
});
|
|
36965
|
+
localSourcebookApp.on(["PATCH", "POST"], "/submissions/:id/draft", createApiKeyAuth(), (c) => c.json({
|
|
36966
|
+
error: "evidence_refresh_required",
|
|
36967
|
+
message: "Owner-authored listing payloads are not accepted. Request a refresh so MCP Scraper can reacquire and compile the public evidence."
|
|
36968
|
+
}, 409));
|
|
36936
36969
|
localSourcebookApp.post("/submissions/:id/refresh", createApiKeyAuth(), async (c) => {
|
|
36937
36970
|
const user = c.get("user");
|
|
36938
36971
|
if (!user.subscription_tier) return c.json({ error: "subscription_required" }, 402);
|
|
36939
|
-
|
|
36940
|
-
|
|
36941
|
-
|
|
36942
|
-
|
|
36972
|
+
try {
|
|
36973
|
+
const submission = await queueLocalSourcebookRefresh(c.req.param("id"), Number(user.id));
|
|
36974
|
+
if (!submission) return c.json({ error: "not_found" }, 404);
|
|
36975
|
+
const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
|
|
36976
|
+
return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(submission.websiteUrl) }, 202);
|
|
36977
|
+
} catch (error) {
|
|
36978
|
+
return c.json({ error: "moderated_listing", message: error instanceof Error ? error.message : String(error) }, 409);
|
|
36979
|
+
}
|
|
36943
36980
|
});
|
|
36944
36981
|
publicLocalSourcebookApp = new import_hono17.Hono();
|
|
36982
|
+
publicLocalSourcebookApp.get("/", async (c) => c.json({ ok: true, listings: await listAllPublicLocalSourcebook() }));
|
|
36983
|
+
publicLocalSourcebookApp.get("/:category", async (c) => c.json({ ok: true, listings: await listAllPublicLocalSourcebook(c.req.param("category")) }));
|
|
36945
36984
|
publicLocalSourcebookApp.get("/:category/:state", async (c) => c.json({ ok: true, listings: await listPublicLocalSourcebook(c.req.param("category"), c.req.param("state").toLowerCase()) }));
|
|
36946
36985
|
publicLocalSourcebookApp.get("/:category/:state/:slug", async (c) => {
|
|
36947
36986
|
const listing = await getPublicLocalSourcebook(c.req.param("category"), c.req.param("state").toLowerCase(), c.req.param("slug"));
|
|
@@ -40959,7 +40998,7 @@ var PACKAGE_VERSION;
|
|
|
40959
40998
|
var init_version = __esm({
|
|
40960
40999
|
"src/version.ts"() {
|
|
40961
41000
|
"use strict";
|
|
40962
|
-
PACKAGE_VERSION = "0.44.
|
|
41001
|
+
PACKAGE_VERSION = "0.44.3";
|
|
40963
41002
|
}
|
|
40964
41003
|
});
|
|
40965
41004
|
|
|
@@ -41125,13 +41164,15 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
|
|
|
41125
41164
|
**get-local-sourcebook-contract**, then **prepare-local-sourcebook-write**, inspect every tag resolution,
|
|
41126
41165
|
and call **validate-local-sourcebook-write**. Call **local-sourcebook-capture** only when validation returns
|
|
41127
41166
|
\`valid:true\`.
|
|
41128
|
-
- A new capture
|
|
41129
|
-
|
|
41130
|
-
|
|
41131
|
-
|
|
41132
|
-
|
|
41133
|
-
-
|
|
41134
|
-
|
|
41167
|
+
- A new capture queues paid broad website, exact Maps place, maximum-accessible review, service-area, staff,
|
|
41168
|
+
and genuine-media acquisition. When compilation succeeds, that exact system-authored evidence revision
|
|
41169
|
+
publishes automatically. Never supply owner-authored services, reviews, images, or other public claims.
|
|
41170
|
+
- Read progress and the compiled record with **local_sourcebook_submission_status**. Use
|
|
41171
|
+
**local_sourcebook_refresh** only when the owner intentionally wants to pay for a new acquisition pass.
|
|
41172
|
+
- Capture and status responses return \`publicUrls.profileUrl\` and \`publicUrls.reviewsUrl\`. Always give those
|
|
41173
|
+
exact links to the user; do not report a listing as live without including its clickable profile URL.
|
|
41174
|
+
- The last published revision remains public during refresh. Administrators can reject or unpublish an
|
|
41175
|
+
exceptional record, but routine subscriber publication does not require administrator review.
|
|
41135
41176
|
|
|
41136
41177
|
## Notes
|
|
41137
41178
|
- For current prices, balances, or limits, call \`credits_info\`. The public machine-readable rate contract is
|
|
@@ -41755,7 +41796,7 @@ var init_contracts = __esm({
|
|
|
41755
41796
|
});
|
|
41756
41797
|
|
|
41757
41798
|
// src/mcp/mcp-tool-schemas.ts
|
|
41758
|
-
var import_zod41, WEBSITE_URL_OR_DOMAIN_ERROR, WebsiteUrlOrDomainSchema, HarvestPaaInputSchema, ExtractUrlBaseInputSchema, ExtractUrlInputSchema, ExtractUrlLocalInputSchema, DiffPageBaseInputSchema, DiffPageInputSchema, DiffPageLocalInputSchema, MapSiteUrlsInputSchema, MapWaybackSnapshotsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, CheckSiteExportInputSchema, ArchiveReadInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, RedditTrendingInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, LocationMarketsInputSchema, CommonsSearchEntitiesInputSchema, CommonsGetEntityInputSchema, CommonsFeaturedImageInputSchema, CommonsMediaInputSchema, CommonsCitationInputSchema, CommonsSourceInputSchema, CommonsRelatedLinkInputSchema, CommonsPrepareEntityInputSchema, CommonsSubmitEntityInputSchema, CommonsValidateEntityInputSchema, CommonsGetEntityLedgerInputSchema, CommonsSaveFilterInputSchema, CommonsListFiltersInputSchema, CommonsListNeedsLinksInputSchema, CommonsGenericOutputSchema, DirectoryWorkflowStatusInputSchema, LocalSourcebookSubmitInputSchema, LocalSourcebookCategorySchema, LocalSourcebookTagCandidateObjectSchema, LocalSourcebookTagDecisionObjectSchema, LocalSourcebookIdentityObjectSchema, GetLocalSourcebookContractInputSchema, ListLocalSourcebookTagsInputSchema, ResolveLocalSourcebookTagsInputSchema, PrepareLocalSourcebookWriteInputSchema, ValidateLocalSourcebookWriteInputSchema, LocalSourcebookCaptureInputSchema, LocalSourcebookSubmissionStatusInputSchema,
|
|
41799
|
+
var import_zod41, WEBSITE_URL_OR_DOMAIN_ERROR, WebsiteUrlOrDomainSchema, HarvestPaaInputSchema, ExtractUrlBaseInputSchema, ExtractUrlInputSchema, ExtractUrlLocalInputSchema, DiffPageBaseInputSchema, DiffPageInputSchema, DiffPageLocalInputSchema, MapSiteUrlsInputSchema, MapWaybackSnapshotsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, CheckSiteExportInputSchema, ArchiveReadInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, RedditTrendingInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, LocationMarketsInputSchema, CommonsSearchEntitiesInputSchema, CommonsGetEntityInputSchema, CommonsFeaturedImageInputSchema, CommonsMediaInputSchema, CommonsCitationInputSchema, CommonsSourceInputSchema, CommonsRelatedLinkInputSchema, CommonsPrepareEntityInputSchema, CommonsSubmitEntityInputSchema, CommonsValidateEntityInputSchema, CommonsGetEntityLedgerInputSchema, CommonsSaveFilterInputSchema, CommonsListFiltersInputSchema, CommonsListNeedsLinksInputSchema, CommonsGenericOutputSchema, DirectoryWorkflowStatusInputSchema, LocalSourcebookSubmitInputSchema, LocalSourcebookCategorySchema, LocalSourcebookTagCandidateObjectSchema, LocalSourcebookTagDecisionObjectSchema, LocalSourcebookIdentityObjectSchema, GetLocalSourcebookContractInputSchema, ListLocalSourcebookTagsInputSchema, ResolveLocalSourcebookTagsInputSchema, PrepareLocalSourcebookWriteInputSchema, ValidateLocalSourcebookWriteInputSchema, LocalSourcebookCaptureInputSchema, LocalSourcebookSubmissionStatusInputSchema, LocalSourcebookRefreshInputSchema, LocalSourcebookOutputSchema, ArtifactPointerOutputSchema, EditorialReadingRoomSiteSchema, EditorialReadingRoomArticleSchema, EditorialReadingRoomGuideInputSchema, EditorialReadingRoomGuideOutputSchema, CreateEditorialReadingRoomInputSchema, EditorialReadingRoomArtifactSchema, CreateEditorialReadingRoomOutputSchema, RenewEditorialReadingRoomDownloadInputSchema, RenewEditorialReadingRoomDownloadOutputSchema, RankTrackerModeSchema, RankTrackerBlueprintInputSchema, NullableString, MapsSearchAttemptOutput, MapsSearchOutputSchema, DirectoryMapsBusinessOutput, DirectoryCsvArtifactOutput, DirectoryWorkflowOutputSchema, LocationDatasetProvenanceOutput, LocationMarketsOutputSchema, RankTrackerToolPlanOutput, RankTrackerTableOutput, RankTrackerCronJobOutput, RankTrackerBlueprintOutputSchema, OrganicResultOutput, AiOverviewOutput, EntityIdsOutput, HarvestPaaOutputSchema, SearchSerpOutputSchema, ExtractUrlOutputSchema, DiffPageOutputSchema, ExtractSiteOutputSchema, AuditSiteOutputSchema, CheckSiteExportOutputSchema, ArchiveEntryOutputSchema, ArchiveReadOutputSchema, MapsPlaceIntelOutputSchema, TrustpilotReviewsOutputSchema, G2ReviewsOutputSchema, CreditsInfoOutputSchema, MapSiteUrlsOutputSchema, WaybackCaptureOutputSchema, MapWaybackSnapshotsOutputSchema, YoutubeHarvestOutputSchema, FacebookAdSearchOutputSchema, VideoFrameAnalysisOutputSchema, VideoFrameAnalysisStatusOutputSchema, RedditThreadOutputSchema, RedditTrendingOutputSchema, FacebookPageIntelOutputSchema, GoogleAdsSearchOutputSchema, GoogleAdsPageIntelOutputSchema, TranscriptSignalOutput, FacebookVideoTranscribeOutputSchema, TranscriptChunkOutput, InstagramBrowserOutput, InstagramPaginationOutput, InstagramProfileContentOutputSchema, InstagramMediaTrackOutput, InstagramDownloadOutput, InstagramMediaDownloadOutputSchema, YoutubeTranscribeOutputSchema, FacebookAdTranscribeOutputSchema, GoogleAdsTranscribeOutputSchema, CaptureSerpSnapshotOutputSchema, CaptureSerpPageSnapshotsOutputSchema, CreditsInfoInputSchema, WorkflowIdSchema2, WorkflowListInputSchema, WorkflowSuggestInputSchema, WorkflowRunInputSchema, WorkflowStepInputSchema, WorkflowStatusInputSchema, WorkflowArtifactReadInputSchema, WorkflowRecipeOutput, WorkflowDefinitionOutput, WorkflowArtifactOutput, WorkflowListOutputSchema, WorkflowSuggestOutputSchema, WorkflowRunOutputSchema, WorkflowStepOutputSchema, WorkflowStatusOutputSchema, WorkflowArtifactReadOutputSchema, SearchSerpInputSchema, CaptureSerpSnapshotInputSchema, ScreenshotInputSchema, CaptureSerpPageSnapshotsInputSchema, ReportArtifactReadInputSchema, ReportArtifactReadOutputSchema, ListServiceConnectionsInputSchema, ListServiceConnectionsOutputSchema, TestServiceConnectionInputSchema, TestServiceConnectionOutputSchema, ReadServiceConnectionInputSchema, ReadServiceConnectionOutputSchema, MetaAdCreativeMediaInputSchema, MetaAdCreativeMediaOutputSchema, ImportServiceConnectionToMemoryInputSchema, ImportServiceConnectionToMemoryOutputSchema, DescribeServiceConnectionToolInputSchema, DescribeServiceConnectionToolOutputSchema, ConnectedDataContinuationSchema, ExportConnectedServiceDataInputSchema, ConnectedDataArtifactSchema, ExportConnectedServiceDataOutputSchema, SearchConsoleTableColumnSchema, SearchConsoleTableFilterSchema, ExportSearchConsoleTableDataInputSchema, ExportSearchConsoleTableDataOutputSchema, RenewConnectedDataExportDownloadInputSchema, RenewConnectedDataExportDownloadOutputSchema, CallServiceConnectionActionInputSchema, CallServiceConnectionActionOutputSchema, SetScheduledActionConnectionsInputSchema, SetScheduledActionConnectionsOutputSchema, SlackSendMessageInputSchema, SlackSendMessageOutputSchema, GmailSendMessageInputSchema, GmailSendMessageOutputSchema, GmailSearchContactsInputSchema, GmailSearchContactsOutputSchema, GoogleCalendarCreateEventInputSchema, GoogleCalendarCreateEventOutputSchema, ZoomCreateMeetingInputSchema, ZoomCreateMeetingOutputSchema;
|
|
41759
41800
|
var init_mcp_tool_schemas = __esm({
|
|
41760
41801
|
"src/mcp/mcp-tool-schemas.ts"() {
|
|
41761
41802
|
"use strict";
|
|
@@ -42276,24 +42317,17 @@ var init_mcp_tool_schemas = __esm({
|
|
|
42276
42317
|
tagCandidates: import_zod41.z.array(LocalSourcebookTagCandidateObjectSchema).max(20).optional()
|
|
42277
42318
|
};
|
|
42278
42319
|
ValidateLocalSourcebookWriteInputSchema = {
|
|
42279
|
-
identity: LocalSourcebookIdentityObjectSchema.
|
|
42280
|
-
listing: import_zod41.z.record(import_zod41.z.string(), import_zod41.z.unknown()).optional().describe("Complete replacement listing draft for an existing owner-scoped submission."),
|
|
42281
|
-
submissionId: import_zod41.z.string().trim().min(1).optional().describe("Existing owner-scoped submission being revised. Omit for a new capture."),
|
|
42282
|
-
baseRevision: import_zod41.z.number().int().min(1).optional().describe("Required current draft revision for an edit, preventing silent overwrites."),
|
|
42320
|
+
identity: LocalSourcebookIdentityObjectSchema.describe("New-listing identity returned by prepare-local-sourcebook-write. Evidence-bearing public fields are compiled by MCP Scraper and cannot be supplied here."),
|
|
42283
42321
|
tagCandidates: import_zod41.z.array(LocalSourcebookTagCandidateObjectSchema).max(20).optional(),
|
|
42284
42322
|
tagDecisions: import_zod41.z.array(LocalSourcebookTagDecisionObjectSchema).max(20).optional()
|
|
42285
42323
|
};
|
|
42286
42324
|
LocalSourcebookCaptureInputSchema = {
|
|
42287
42325
|
...ValidateLocalSourcebookWriteInputSchema,
|
|
42288
|
-
idempotencyKey: import_zod41.z.string().trim().min(8).max(200).optional().describe("Stable retry key for a new capture. Required
|
|
42326
|
+
idempotencyKey: import_zod41.z.string().trim().min(8).max(200).optional().describe("Stable retry key for a new capture. Required either here or in identity.")
|
|
42289
42327
|
};
|
|
42290
42328
|
LocalSourcebookSubmissionStatusInputSchema = {
|
|
42291
42329
|
submissionId: import_zod41.z.string().trim().min(1).describe("The owner-scoped submission ID returned by local-sourcebook-capture.")
|
|
42292
42330
|
};
|
|
42293
|
-
LocalSourcebookUpdateDraftInputSchema = {
|
|
42294
|
-
submissionId: import_zod41.z.string().trim().min(1),
|
|
42295
|
-
payload: import_zod41.z.record(import_zod41.z.string(), import_zod41.z.unknown()).describe("Complete replacement draft. The previous revision remains immutable in the audit history.")
|
|
42296
|
-
};
|
|
42297
42331
|
LocalSourcebookRefreshInputSchema = {
|
|
42298
42332
|
submissionId: import_zod41.z.string().trim().min(1).describe("Owner-scoped listing submission to re-crawl and refresh.")
|
|
42299
42333
|
};
|
|
@@ -45216,7 +45250,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
45216
45250
|
}, async (input) => formatDirectoryWorkflow(await executor.directoryWorkflowStatus(input), input, ctx));
|
|
45217
45251
|
server.registerTool("get-local-sourcebook-contract", {
|
|
45218
45252
|
title: "Get Local Sourcebook Contract",
|
|
45219
|
-
description: "Read the governed listing purpose, supported categories,
|
|
45253
|
+
description: "Read the governed listing purpose, supported categories, exact LocalSourcebook.com profile/review URLs, nationwide directory URL, required sections, acquisition limits, tag policy, ownership boundary, and automatic evidence-publication rule. Call this before composing a listing when its required shape is uncertain.",
|
|
45220
45254
|
inputSchema: GetLocalSourcebookContractInputSchema,
|
|
45221
45255
|
outputSchema: recordOutputSchema("get-local-sourcebook-contract", LocalSourcebookOutputSchema),
|
|
45222
45256
|
annotations: localPlanningToolAnnotations("Get Local Sourcebook Contract")
|
|
@@ -45244,28 +45278,28 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
45244
45278
|
}, async (input) => executor.prepareLocalSourcebookWrite(input));
|
|
45245
45279
|
server.registerTool("validate-local-sourcebook-write", {
|
|
45246
45280
|
title: "Validate Local Sourcebook Write",
|
|
45247
|
-
description: "Validate a proposed new listing
|
|
45281
|
+
description: "Validate a proposed new listing identity without writing it. Checks business identity, canonical tags, and explicit tag decisions. Public facts are compiled from MCP Scraper evidence rather than accepted from the owner. Capture only when valid is true.",
|
|
45248
45282
|
inputSchema: ValidateLocalSourcebookWriteInputSchema,
|
|
45249
45283
|
outputSchema: recordOutputSchema("validate-local-sourcebook-write", LocalSourcebookOutputSchema),
|
|
45250
45284
|
annotations: localPlanningToolAnnotations("Validate Local Sourcebook Write")
|
|
45251
45285
|
}, async (input) => executor.validateLocalSourcebookWrite(input));
|
|
45252
45286
|
server.registerTool("local-sourcebook-capture", {
|
|
45253
45287
|
title: "Capture Governed Local Sourcebook Listing",
|
|
45254
|
-
description: "Strict owner-scoped write path after list, contract, prepare, and validate.
|
|
45288
|
+
description: "Strict owner-scoped write path after list, contract, prepare, and validate. Capture registers canonical tags, returns the exact LocalSourcebook.com profile and reviews URLs, and queues paid website, exact-place, review, service-area, staff, and genuine-media acquisition. A successful system-compiled evidence revision publishes automatically; owner-authored public claims are not accepted.",
|
|
45255
45289
|
inputSchema: LocalSourcebookCaptureInputSchema,
|
|
45256
45290
|
outputSchema: recordOutputSchema("local-sourcebook-capture", LocalSourcebookOutputSchema),
|
|
45257
45291
|
annotations: liveWebToolAnnotations("Capture Governed Local Sourcebook Listing")
|
|
45258
45292
|
}, async (input) => executor.localSourcebookCapture(input));
|
|
45259
45293
|
server.registerTool("local_sourcebook_submission_status", {
|
|
45260
45294
|
title: "Local Sourcebook Submission Status",
|
|
45261
|
-
description: "Read the authenticated caller\u2019s listing draft, enrichment coverage, immutable revision number, and
|
|
45295
|
+
description: "Read the authenticated caller\u2019s listing draft, enrichment coverage, immutable revision number, publication state, and exact live LocalSourcebook.com profile and reviews URLs.",
|
|
45262
45296
|
inputSchema: LocalSourcebookSubmissionStatusInputSchema,
|
|
45263
45297
|
outputSchema: recordOutputSchema("local_sourcebook_submission_status", LocalSourcebookOutputSchema),
|
|
45264
45298
|
annotations: localPlanningToolAnnotations("Local Sourcebook Submission Status")
|
|
45265
45299
|
}, async (input) => executor.localSourcebookSubmissionStatus(input));
|
|
45266
45300
|
server.registerTool("local_sourcebook_refresh", {
|
|
45267
45301
|
title: "Refresh a Local Sourcebook Listing",
|
|
45268
|
-
description: "Queue a new broad crawl and review/media acquisition pass for a listing owned by the authenticated MCP Scraper account.",
|
|
45302
|
+
description: "Queue a new broad crawl and review/media acquisition pass for a listing owned by the authenticated MCP Scraper account. The last published revision remains public until the refreshed evidence revision completes and auto-publishes.",
|
|
45269
45303
|
inputSchema: LocalSourcebookRefreshInputSchema,
|
|
45270
45304
|
outputSchema: recordOutputSchema("local_sourcebook_refresh", LocalSourcebookOutputSchema),
|
|
45271
45305
|
annotations: liveWebToolAnnotations("Refresh a Local Sourcebook Listing")
|
|
@@ -45891,9 +45925,6 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
45891
45925
|
localSourcebookSubmissionStatus(input) {
|
|
45892
45926
|
return this.getJson(`/local-sourcebook/submissions/${encodeURIComponent(input.submissionId)}`);
|
|
45893
45927
|
}
|
|
45894
|
-
localSourcebookUpdateDraft(input) {
|
|
45895
|
-
return this.call(`/local-sourcebook/submissions/${encodeURIComponent(input.submissionId)}/draft`, { payload: input.payload });
|
|
45896
|
-
}
|
|
45897
45928
|
localSourcebookRefresh(input) {
|
|
45898
45929
|
return this.call(`/local-sourcebook/submissions/${encodeURIComponent(input.submissionId)}/refresh`, {});
|
|
45899
45930
|
}
|