seo 0.2.7 → 0.2.8
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 +1 -1
- package/dist/cli.js +2 -2
- package/dist/{dist-C0LWlNAw.js → dist-B8eKKp3B.js} +3 -3
- package/dist/{dist-C0LWlNAw.js.map → dist-B8eKKp3B.js.map} +1 -1
- package/dist/{dist-B6UxI6sc.js → dist-DkWLBABR.js} +1 -1
- package/dist/index.js +51 -35
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +51 -35
- package/dist/mcp.js.map +1 -1
- package/dist/{package-BI-bLeV4.js → package-BDez60C3.js} +2 -2
- package/dist/{package-BI-bLeV4.js.map → package-BDez60C3.js.map} +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __seoCreateRequire } from 'node:module'; const require = __seoCreateRequire(import.meta.url);
|
|
3
|
-
import{s as e}from"./dist-
|
|
3
|
+
import{s as e}from"./dist-B8eKKp3B.js";export{e as startMcpServer};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __seoCreateRequire } from 'node:module'; const require = __seoCreateRequire(import.meta.url);
|
|
2
|
-
import { n as load, t as version } from "./package-
|
|
2
|
+
import { n as load, t as version } from "./package-BDez60C3.js";
|
|
3
3
|
import { Headers, fetch as fetch$1 } from "undici";
|
|
4
4
|
import { chmodSync, createWriteStream, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { arch, homedir, platform } from "node:os";
|
|
@@ -6797,16 +6797,15 @@ async function inspectMarkdownPage(input) {
|
|
|
6797
6797
|
repeatedHashStable: null,
|
|
6798
6798
|
markdownCanonicalMatchesHtml: null
|
|
6799
6799
|
};
|
|
6800
|
-
|
|
6801
|
-
const explicitUrl = advertisedUrls[0];
|
|
6800
|
+
const explicitUrl = advertisedUrls.length === 1 ? advertisedUrls[0] : void 0;
|
|
6802
6801
|
const [explicit, negotiated, repeated] = await Promise.all([
|
|
6803
|
-
fetchRepresentation({
|
|
6802
|
+
explicitUrl ? fetchRepresentation({
|
|
6804
6803
|
url: explicitUrl,
|
|
6805
6804
|
accept: "text/markdown",
|
|
6806
6805
|
timeoutMs: input.timeoutMs,
|
|
6807
6806
|
fetch: input.fetch,
|
|
6808
6807
|
signal: input.signal
|
|
6809
|
-
}),
|
|
6808
|
+
}) : Promise.resolve(void 0),
|
|
6810
6809
|
fetchRepresentation({
|
|
6811
6810
|
url: input.page.finalUrl,
|
|
6812
6811
|
accept: "text/markdown",
|
|
@@ -6815,20 +6814,21 @@ async function inspectMarkdownPage(input) {
|
|
|
6815
6814
|
signal: input.signal
|
|
6816
6815
|
}),
|
|
6817
6816
|
fetchRepresentation({
|
|
6818
|
-
url: explicitUrl,
|
|
6817
|
+
url: explicitUrl ?? input.page.finalUrl,
|
|
6819
6818
|
accept: "text/markdown",
|
|
6820
6819
|
timeoutMs: input.timeoutMs,
|
|
6821
6820
|
fetch: input.fetch,
|
|
6822
6821
|
signal: input.signal
|
|
6823
6822
|
})
|
|
6824
6823
|
]);
|
|
6825
|
-
observation.explicit = explicit.observation;
|
|
6824
|
+
if (explicit) observation.explicit = explicit.observation;
|
|
6826
6825
|
observation.negotiated = negotiated.observation;
|
|
6827
6826
|
observation.repeated = repeated.observation;
|
|
6828
|
-
observation.explicitMatchesNegotiated = explicit
|
|
6829
|
-
|
|
6830
|
-
observation.
|
|
6831
|
-
|
|
6827
|
+
observation.explicitMatchesNegotiated = explicit?.observation.sha256 && negotiated.observation.sha256 ? explicit.observation.sha256 === negotiated.observation.sha256 : null;
|
|
6828
|
+
const primary = explicit ?? negotiated;
|
|
6829
|
+
observation.repeatedHashStable = primary.observation.sha256 && repeated.observation.sha256 ? primary.observation.sha256 === repeated.observation.sha256 : null;
|
|
6830
|
+
observation.markdownCanonicalMatchesHtml = sameDocument(primary.observation.canonicalUrl, input.page.finalUrl);
|
|
6831
|
+
if (primary.body) observation.quality = markdownQuality(primary.body, input.page);
|
|
6832
6832
|
return observation;
|
|
6833
6833
|
}
|
|
6834
6834
|
async function fetchText(input) {
|
|
@@ -7164,10 +7164,13 @@ async function collectAgentDiscovery(input) {
|
|
|
7164
7164
|
const wwwLocation = www.location ? new URL(www.location, wwwUrl).toString() : void 0;
|
|
7165
7165
|
const qZeroContentType = qZero.observation.contentType;
|
|
7166
7166
|
const advertisedPages = observations.filter((observation) => observation.htmlAlternateUnique).length;
|
|
7167
|
-
const evaluatedPages = observations.filter((observation) =>
|
|
7167
|
+
const evaluatedPages = observations.filter((observation) => {
|
|
7168
|
+
const representation = observation.explicit ?? observation.negotiated;
|
|
7169
|
+
return representation?.status !== void 0 && representation.status >= 200 && representation.status < 300 && /^\s*text\/markdown\b/iu.test(representation.contentType ?? "");
|
|
7170
|
+
}).length;
|
|
7168
7171
|
const warnings = [...pages.length !== input.pages.length ? [`Agent representations were evaluated for ${pages.length} successful HTML pages from ${input.pages.length} retained documents.`] : [], ...routeManifest.valid ? [] : ["No valid public agent route manifest was available for orphan checks."]].sort();
|
|
7169
7172
|
const htmlContentSignals = pages.map((page) => headerValue$1(page.responseHeaders, "content-signal")).filter((value) => Boolean(value));
|
|
7170
|
-
const markdownContentSignals = observations.map((observation) => observation.explicit?.contentSignal).filter((value) => Boolean(value));
|
|
7173
|
+
const markdownContentSignals = observations.map((observation) => observation.explicit?.contentSignal ?? observation.negotiated?.contentSignal).filter((value) => Boolean(value));
|
|
7171
7174
|
const contentSignalValues = [.../* @__PURE__ */ new Set([...htmlContentSignals, ...markdownContentSignals])].sort();
|
|
7172
7175
|
return {
|
|
7173
7176
|
profile: "content",
|
|
@@ -7250,7 +7253,11 @@ function section$1(id, title, checks) {
|
|
|
7250
7253
|
};
|
|
7251
7254
|
}
|
|
7252
7255
|
function failedMarkdownUrls(discovery) {
|
|
7253
|
-
return discovery.markdownAlternates.pages.filter((page) =>
|
|
7256
|
+
return discovery.markdownAlternates.pages.filter((page) => {
|
|
7257
|
+
const negotiatedOk = page.negotiated?.status === 200 && /^\s*text\/markdown\b/iu.test(page.negotiated.contentType ?? "") && page.negotiated.varyAccept;
|
|
7258
|
+
const explicitOk = !page.htmlAlternateUnique ? true : page.httpAlternateUrls.length === 1 && page.explicit?.status === 200 && /^\s*text\/markdown\b/iu.test(page.explicit.contentType ?? "") && page.explicitMatchesNegotiated === true && page.markdownCanonicalMatchesHtml === true;
|
|
7259
|
+
return !negotiatedOk || !explicitOk || page.repeatedHashStable !== true;
|
|
7260
|
+
}).map((page) => page.htmlUrl);
|
|
7254
7261
|
}
|
|
7255
7262
|
function qualityFailureUrls(discovery) {
|
|
7256
7263
|
return discovery.markdownAlternates.pages.filter((page) => {
|
|
@@ -7292,20 +7299,25 @@ function markdownChecks(discovery) {
|
|
|
7292
7299
|
const markdown = discovery.markdownAlternates;
|
|
7293
7300
|
const failedUrls = failedMarkdownUrls(discovery);
|
|
7294
7301
|
const qualityUrls = qualityFailureUrls(discovery);
|
|
7295
|
-
const
|
|
7296
|
-
const
|
|
7302
|
+
const negotiatedPages = markdown.pages.filter((page) => page.negotiated?.status === 200 && /^\s*text\/markdown\b/iu.test(page.negotiated.contentType ?? "")).length;
|
|
7303
|
+
const explicitPages = markdown.pages.filter((page) => page.htmlAlternateUnique).length;
|
|
7304
|
+
const coverageComplete = markdown.eligibleHtmlPages > 0 && markdown.evaluatedPages === markdown.eligibleHtmlPages;
|
|
7305
|
+
const negotiationComplete = markdown.eligibleHtmlPages > 0 && negotiatedPages === markdown.eligibleHtmlPages && markdown.pages.every((page) => page.negotiated?.varyAccept) && markdown.pages.every((page) => !page.htmlAlternateUnique || page.explicitMatchesNegotiated === true);
|
|
7297
7306
|
const stable = markdown.eligibleHtmlPages > 0 && markdown.stableResponses === markdown.eligibleHtmlPages;
|
|
7298
|
-
const tokenHeaders = markdown.pages.filter((page) =>
|
|
7307
|
+
const tokenHeaders = markdown.pages.filter((page) => {
|
|
7308
|
+
return (page.explicit ?? page.negotiated)?.markdownTokens !== void 0 && (!page.explicit || !page.negotiated || page.explicit.markdownTokens === page.negotiated.markdownTokens);
|
|
7309
|
+
}).length;
|
|
7299
7310
|
return [
|
|
7300
7311
|
check$1("representations", {
|
|
7301
7312
|
id: "markdown-coverage",
|
|
7302
7313
|
status: markdown.eligibleHtmlPages === 0 ? "unknown" : coverageComplete ? "pass" : "fail",
|
|
7303
|
-
title: coverageComplete ? "Every successful HTML page
|
|
7304
|
-
plainEnglish: `${markdown.
|
|
7305
|
-
action: coverageComplete ? "Keep
|
|
7314
|
+
title: coverageComplete ? "Every successful HTML page has a Markdown representation" : "Markdown representation coverage is incomplete",
|
|
7315
|
+
plainEnglish: `${markdown.evaluatedPages} of ${markdown.eligibleHtmlPages} successful HTML pages returned Markdown. ${explicitPages} advertised an explicit alternative and ${negotiatedPages} supported content negotiation.`,
|
|
7316
|
+
action: coverageComplete ? "Keep the negotiated or explicit Markdown response stable as routes change." : "Return text/markdown through content negotiation or advertise one working Markdown alternative for each public HTML page.",
|
|
7306
7317
|
evidence: {
|
|
7307
7318
|
eligibleHtmlPages: markdown.eligibleHtmlPages,
|
|
7308
7319
|
advertisedPages: markdown.advertisedPages,
|
|
7320
|
+
negotiatedPages,
|
|
7309
7321
|
evaluatedPages: markdown.evaluatedPages
|
|
7310
7322
|
},
|
|
7311
7323
|
urls: failedUrls.slice(0, 25)
|
|
@@ -7313,18 +7325,22 @@ function markdownChecks(discovery) {
|
|
|
7313
7325
|
check$1("representations", {
|
|
7314
7326
|
id: "markdown-token-estimates",
|
|
7315
7327
|
status: markdown.evaluatedPages === 0 ? "unknown" : tokenHeaders === markdown.evaluatedPages ? "pass" : "warning",
|
|
7316
|
-
title: tokenHeaders === markdown.evaluatedPages ? "Every Markdown response includes
|
|
7317
|
-
plainEnglish: `${tokenHeaders} of ${markdown.evaluatedPages} evaluated pages returned
|
|
7318
|
-
action: "
|
|
7319
|
-
urls: markdown.pages.filter((page) =>
|
|
7328
|
+
title: tokenHeaders === markdown.evaluatedPages ? "Every Markdown response includes a token estimate" : "Some Markdown responses are missing a stable token estimate",
|
|
7329
|
+
plainEnglish: `${tokenHeaders} of ${markdown.evaluatedPages} evaluated pages returned X-Markdown-Tokens. Paired explicit and negotiated responses agreed where both existed. The value is an estimate, not an exact model-specific token count.`,
|
|
7330
|
+
action: "Return a stable token estimate and keep it consistent when both explicit and negotiated responses exist.",
|
|
7331
|
+
urls: markdown.pages.filter((page) => {
|
|
7332
|
+
return (page.explicit ?? page.negotiated)?.markdownTokens === void 0 || page.explicit !== void 0 && page.negotiated !== void 0 && page.explicit.markdownTokens !== page.negotiated.markdownTokens;
|
|
7333
|
+
}).map((page) => page.htmlUrl).slice(0, 25)
|
|
7320
7334
|
}),
|
|
7321
7335
|
check$1("representations", {
|
|
7322
7336
|
id: "markdown-negotiation",
|
|
7323
|
-
status: markdown.eligibleHtmlPages === 0 ? "unknown" :
|
|
7324
|
-
title:
|
|
7325
|
-
plainEnglish: `${
|
|
7326
|
-
action: "
|
|
7337
|
+
status: markdown.eligibleHtmlPages === 0 ? "unknown" : negotiationComplete && discovery.contentNegotiation.qZeroHonoured ? "pass" : "fail",
|
|
7338
|
+
title: negotiationComplete && discovery.contentNegotiation.qZeroHonoured ? "Markdown content negotiation works across the site" : "Markdown content negotiation needs attention",
|
|
7339
|
+
plainEnglish: `${negotiatedPages} of ${markdown.eligibleHtmlPages} pages returned negotiated Markdown. ${markdown.exactByteMatches} of ${explicitPages} paired explicit responses matched byte for byte. A request that refuses Markdown ${discovery.contentNegotiation.qZeroHonoured ? "received HTML" : "did not produce confirmed HTML evidence"}.`,
|
|
7340
|
+
action: "Honour Accept q-values, send Vary: Accept, and keep paired explicit and negotiated responses identical when both exist.",
|
|
7327
7341
|
evidence: {
|
|
7342
|
+
negotiatedPages,
|
|
7343
|
+
explicitPages,
|
|
7328
7344
|
exactByteMatches: markdown.exactByteMatches,
|
|
7329
7345
|
qZero: discovery.contentNegotiation
|
|
7330
7346
|
},
|
|
@@ -7334,8 +7350,8 @@ function markdownChecks(discovery) {
|
|
|
7334
7350
|
id: "markdown-determinism",
|
|
7335
7351
|
status: markdown.eligibleHtmlPages === 0 ? "unknown" : stable ? "pass" : "fail",
|
|
7336
7352
|
title: stable ? "Repeated Markdown responses are stable" : "Repeated Markdown responses changed during the audit",
|
|
7337
|
-
plainEnglish: `${markdown.stableResponses} of ${markdown.eligibleHtmlPages} repeated
|
|
7338
|
-
action: "
|
|
7353
|
+
plainEnglish: `${markdown.stableResponses} of ${markdown.eligibleHtmlPages} repeated Markdown responses kept the same SHA-256 digest.`,
|
|
7354
|
+
action: "Remove timestamps, random output, or other runtime rewriting that changes the same Markdown response between requests.",
|
|
7339
7355
|
evidence: { stableResponses: markdown.stableResponses },
|
|
7340
7356
|
urls: failedUrls.slice(0, 25)
|
|
7341
7357
|
}),
|
|
@@ -7449,10 +7465,10 @@ function identityChecks(report) {
|
|
|
7449
7465
|
const officialProfiles = [...new Set(report.pages.flatMap((page) => [...page.schemaSameAs ?? [], ...page.socialProfileLinks ?? []]))];
|
|
7450
7466
|
return [check$1("identity", {
|
|
7451
7467
|
id: "identity-graph",
|
|
7452
|
-
status:
|
|
7453
|
-
title:
|
|
7454
|
-
plainEnglish: `
|
|
7455
|
-
action: "Connect truthful
|
|
7468
|
+
status: hasWebsite && hasCreator && pageTypes.length > 0 ? "pass" : "warning",
|
|
7469
|
+
title: hasWebsite && hasCreator && pageTypes.length > 0 ? "Structured identity covers the website, creator, and pages" : "The structured identity graph is missing a useful entity layer",
|
|
7470
|
+
plainEnglish: `Website identity: ${hasWebsite ? "present" : "missing"}. Creator or publisher identity: ${hasCreator ? "present" : "missing"}. Page-level types: ${pageTypes.length ? pageTypes.join(", ") : "missing"}. Software identity: ${hasSoftware ? "present" : "not observed and not required for a content site"}.`,
|
|
7471
|
+
action: "Connect truthful WebSite, creator or publisher, and page nodes. Add SoftwareApplication only when the site actually represents software. Use sameAs only for official profiles that identify the same entity.",
|
|
7456
7472
|
evidence: {
|
|
7457
7473
|
schemaTypes: [...types].sort(),
|
|
7458
7474
|
officialProfiles: officialProfiles.sort()
|
|
@@ -7940,7 +7956,7 @@ function aiReadiness(report) {
|
|
|
7940
7956
|
score: 0,
|
|
7941
7957
|
evaluated: Boolean(agentDiscovery),
|
|
7942
7958
|
title: agentDiscovery ? "Markdown alternatives were checked" : "Markdown alternatives were not evaluated",
|
|
7943
|
-
plainEnglish: agentDiscovery ? `${agentDiscovery.markdownAlternates.
|
|
7959
|
+
plainEnglish: agentDiscovery ? `${agentDiscovery.markdownAlternates.evaluatedPages} of ${agentDiscovery.markdownAlternates.eligibleHtmlPages} successful HTML pages returned Markdown through an explicit alternative or content negotiation. ${agentDiscovery.markdownAlternates.exactByteMatches} paired explicit responses matched content negotiation byte for byte.` : "This crawl does not include the focused representation checks, so it cannot say whether HTML pages publish stable Markdown alternatives.",
|
|
7944
7960
|
action: "Use the focused agent-readiness report when you need route coverage, content negotiation, byte stability, or extraction-quality evidence.",
|
|
7945
7961
|
evidence: agentDiscovery ? {
|
|
7946
7962
|
eligibleHtmlPages: agentDiscovery.markdownAlternates.eligibleHtmlPages,
|