seo 0.12.0 → 0.12.1
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/PRIVACY.md +57 -3
- package/dist/cli.js +2 -2
- package/dist/{dist-B1bivk1S.js → dist-GOZ_hkEB.js} +1 -1
- package/dist/{dist-Ban8uP1U.js → dist-U5Io-lSG.js} +104 -88
- package/dist/dist-U5Io-lSG.js.map +1 -0
- package/dist/{esm-CQJgJ8TD.js → esm-Cyusbw2J.js} +2 -2
- package/dist/{esm-CQJgJ8TD.js.map → esm-Cyusbw2J.js.map} +1 -1
- package/dist/index.d.ts +188 -42
- package/dist/index.js +4303 -205
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +412 -58
- package/dist/mcp.js.map +1 -1
- package/package.json +3 -3
- package/dist/dist-Ban8uP1U.js.map +0 -1
package/PRIVACY.md
CHANGED
|
@@ -13,7 +13,8 @@ keeps your Search Console or analytics data, your reports or a log of your
|
|
|
13
13
|
requests. When you first sign up it also notes how you found it: the
|
|
14
14
|
sign-in path, the agent or app, and the site that sent you there. The only
|
|
15
15
|
thing kept about your use is an anonymous usage count (the event, report,
|
|
16
|
-
agent, version and week).
|
|
16
|
+
agent, version and week). Accounts in the weekly site audit beta also have
|
|
17
|
+
their audited sites' crawl results kept, as described below.
|
|
17
18
|
|
|
18
19
|
The command-line tool runs on your machine. It does not create an SEO
|
|
19
20
|
account, upload reports to a hosted SEO service, or send reports or connected
|
|
@@ -38,6 +39,18 @@ Cloudflare D1 with only these things:
|
|
|
38
39
|
- **Your linked Bing account, if you link one.** Its refresh and access
|
|
39
40
|
tokens, with read-only access to Bing Webmaster Tools, and a name made
|
|
40
41
|
from its sites.
|
|
42
|
+
- **Search Console folders you add from the Beta tab.** "Create these in
|
|
43
|
+
Search Console" asks Google, at that moment, for permission to add and
|
|
44
|
+
manage your Search Console properties. The server uses it once, to add
|
|
45
|
+
the folders listed on the page, and does not keep that permission or its
|
|
46
|
+
token. It keeps which folders it added and whether Google verified them.
|
|
47
|
+
- **Alerts, for accounts in the weekly-audit beta.** Which alerts you want
|
|
48
|
+
by email and by webhook, your webhook URL and its signing secret, and
|
|
49
|
+
each alert sent in the last 30 days: the site, the pages that changed
|
|
50
|
+
and whether it was delivered. Alert email goes to your first linked
|
|
51
|
+
Google account's address through PostShiba, our email provider, which
|
|
52
|
+
receives that address and the alert's text to send it. A webhook gets
|
|
53
|
+
the same alert at the URL you save.
|
|
41
54
|
- **Your API keys, if you save them.** A DataForSEO login and password, an
|
|
42
55
|
Ahrefs key and a TypeSafe key.
|
|
43
56
|
- **Your Clicky sites, if you save them.** Each site's numeric site ID,
|
|
@@ -83,7 +96,47 @@ it. The token your MCP client keeps carries only your person id.
|
|
|
83
96
|
|
|
84
97
|
The server keeps nothing else. It does not keep reports, Search Console
|
|
85
98
|
or Google Analytics rows, lists of your sites, or the pages it checked.
|
|
86
|
-
Request logs are turned off.
|
|
99
|
+
Request logs are turned off. The one exception is the weekly site audit
|
|
100
|
+
beta, below, and only for the sites you add to it.
|
|
101
|
+
|
|
102
|
+
### Weekly site audit (beta)
|
|
103
|
+
|
|
104
|
+
The maintainer turns this beta on for chosen accounts; no one else has it.
|
|
105
|
+
For each Search Console property you add on the account page, the server
|
|
106
|
+
crawls the site once a week, up to 5,000 pages, as `SEOSkillBot`, and
|
|
107
|
+
follows the site's `robots.txt`. It keeps, per site:
|
|
108
|
+
|
|
109
|
+
- the property name, when you added it and when the next crawl is due;
|
|
110
|
+
- the latest crawl and the one before it: each page's URL, status,
|
|
111
|
+
redirect target, title, description, first heading, canonical, robots
|
|
112
|
+
settings, word count and the internal links on it with their link text;
|
|
113
|
+
- the findings worked out from them (such as broken links or missing
|
|
114
|
+
titles), with when each was first seen and resolved; resolved findings
|
|
115
|
+
are removed after 90 days;
|
|
116
|
+
- a one-line summary of each of the last 52 crawls (counts only);
|
|
117
|
+
- Google's URL Inspection result for each known URL of the site (the
|
|
118
|
+
sitemap's, the crawl's and the Search Console pages with clicks or
|
|
119
|
+
impressions, up to 50,000 from the sitemap and crawl): its indexing
|
|
120
|
+
reason and Google's details, when it was checked and is due again, the
|
|
121
|
+
reason before it last changed, and when it last dropped out of or came
|
|
122
|
+
back to Google's index. The server checks these in the background each day, within
|
|
123
|
+
Google's 2,000 checks a day per property, and `seo_page` and `seo_index`
|
|
124
|
+
read and add to the same results;
|
|
125
|
+
- for each of those Search Console pages, its clicks and impressions in the
|
|
126
|
+
last 28 days and its clicks in the 28 days before, replaced each day;
|
|
127
|
+
- how many URL Inspection checks each property used today;
|
|
128
|
+
- how many pages a day Google can check for the site, and the folders worth
|
|
129
|
+
adding as their own Search Console properties, with which of them you
|
|
130
|
+
added from the account page.
|
|
131
|
+
|
|
132
|
+
If you click Create these in Search Console, Google asks you for
|
|
133
|
+
permission to manage Search Console for that Google account. The server
|
|
134
|
+
uses that permission once, to add the listed folders as properties and
|
|
135
|
+
read back whether each is verified. It asks for no refresh token and
|
|
136
|
+
keeps no token afterwards.
|
|
137
|
+
|
|
138
|
+
Remove a site on the account page and all of this is deleted at once.
|
|
139
|
+
Delete everything deletes it for every site.
|
|
87
140
|
|
|
88
141
|
- **Your data.** Search Console, Google Analytics, Clicky and provider responses are
|
|
89
142
|
fetched for each request, returned to your MCP client and not kept. Pages checked live are fetched for the request and not kept.
|
|
@@ -112,7 +165,8 @@ Request logs are turned off.
|
|
|
112
165
|
|
|
113
166
|
Sign in at [seoskill.dev/account](https://seoskill.dev/account) and choose
|
|
114
167
|
**Delete everything**. It deletes your person id, linked accounts, keys,
|
|
115
|
-
Clicky sites, linked machines, beta features
|
|
168
|
+
Clicky sites, linked machines, beta features, audited sites with their
|
|
169
|
+
crawl data and how you signed up,
|
|
116
170
|
and revokes the Google sign-ins. Your agents will ask you to sign in again if
|
|
117
171
|
you use the hosted server later. You can also revoke SEO Skill in your
|
|
118
172
|
[Google Account connections](https://myaccount.google.com/connections), which
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __seoCreateRequire } from 'node:module'; const require = __seoCreateRequire(import.meta.url);
|
|
3
|
-
import{$ as e,$n as t,$t as n,A as r,An as i,At as a,B as o,Bn as s,Bt as c,C as l,Cn as u,Ct as d,D as ee,Dn as te,Dt as f,E as ne,En as p,Et as m,F as re,Fn as ie,Ft as ae,G as oe,Gn as se,Gt as ce,H as le,Hn as ue,Ht as de,I as fe,In as pe,It as me,J as he,Jn as ge,Jt as _e,K as ve,Kn as ye,Kt as be,L as xe,Ln as Se,Lt as Ce,M as we,Mn as Te,Mt as Ee,N as De,Nn as Oe,Nt as ke,O as Ae,On as je,Ot as Me,P as Ne,Pn as Pe,Pt as Fe,Q as Ie,Qn as Le,Qt as Re,R as ze,Rn as Be,Rt as Ve,S as He,Sn as Ue,St as We,T as Ge,Tn as Ke,Tt as qe,U as Je,Un as Ye,Ut as Xe,V as Ze,Vn as Qe,Vt as $e,W as et,Wn as tt,Wt as nt,X as rt,Xn as h,Xt as it,Y as at,Yn as ot,Yt as st,Z as ct,Zn as lt,Zt as ut,_ as dt,_n as ft,_t as pt,a as mt,an as ht,at as gt,b as _t,bn as vt,bt as yt,c as bt,cn as xt,ct as St,d as Ct,dn as wt,dt as Tt,en as Et,er as Dt,et as Ot,f as kt,fn as At,ft as jt,g as Mt,gn as Nt,gt as Pt,h as Ft,hn as It,ht as Lt,i as Rt,in as zt,it as Bt,j as Vt,jn as Ht,jt as Ut,k as Wt,kn as Gt,kt as Kt,l as qt,ln as Jt,lt as Yt,m as Xt,mn as Zt,mt as Qt,nn as $t,nt as en,o as tn,on as nn,ot as rn,p as an,pn as on,pt as sn,q as cn,qn as ln,qt as un,rn as dn,rt as fn,sn as pn,st as mn,t as hn,tn as gn,tt as _n,u as vn,un as yn,ut as bn,v as xn,vn as Sn,vt as Cn,w as wn,wn as Tn,wt as En,x as Dn,xn as On,xt as kn,y as An,yn as jn,yt as Mn,z as Nn,zn as Pn,zt as Fn}from"./dist-Ban8uP1U.js";import{arch as In,homedir as Ln,platform as Rn}from"node:os";import{basename as zn,dirname as Bn,join as g,posix as Vn,resolve as Hn,win32 as Un}from"node:path";import{constants as Wn,copyFileSync as Gn,createWriteStream as Kn,existsSync as _,mkdirSync as qn,readFileSync as Jn,readdirSync as Yn,realpathSync as Xn,renameSync as Zn,statSync as Qn,writeFileSync as $n}from"node:fs";import{fileURLToPath as er}from"node:url";import{mkdir as tr,readFile as nr,writeFile as rr}from"node:fs/promises";import{isDeepStrictEqual as ir,stripVTControlCharacters as ar}from"node:util";import{spawn as or,spawnSync as sr}from"node:child_process";import{defineCommand as v,runCommand as cr,runMain as lr}from"citty";import{cancel as ur,confirm as dr,intro as y,isCancel as fr,log as pr,multiselect as mr,note as b,outro as x,password as hr,select as gr,text as _r}from"@clack/prompts";import vr from"picocolors";import yr from"string-width";import br from"cli-table3";import{finished as xr}from"node:stream/promises";import{applyEdits as Sr,modify as Cr,parse as wr,printParseErrorCode as Tr}from"jsonc-parser";import Er from"update-notifier";const S={summary:`workflow.site.generated_at.summary.attribution.confidence.classification.updates_matched.known_confounders.page_segment_status.page_segment_eligible_rows.page_segment_returned_rows.page_segment_limited_rows.page_segment_result_limit.page_segment_source_row_limit.page_segment_source_possibly_truncated.page_segment_warnings.query_segment_status.query_segment_eligible_rows.query_segment_returned_rows.query_segment_limited_rows.query_segment_result_limit.query_segment_source_row_limit.query_segment_source_possibly_truncated.query_segment_warnings.device_segment_status.device_segment_eligible_rows.device_segment_returned_rows.device_segment_limited_rows.device_segment_result_limit.device_segment_source_row_limit.device_segment_source_possibly_truncated.device_segment_warnings.country_segment_status.country_segment_eligible_rows.country_segment_returned_rows.country_segment_limited_rows.country_segment_result_limit.country_segment_source_row_limit.country_segment_source_possibly_truncated.country_segment_warnings`.split(`.`),steps:[`rank`,`tool`,`status`,`summary`],actions:[`rank`,`title`,`confidence`,`action`],findings:[`dimension`,`data_status`,`eligible_rows`,`returned_rows`,`limited_rows`,`result_limit`,`unmatched_rows`,`summary`,`winner_key`,`winner_click_delta`,`winner_impression_delta`,`winner_position_delta`,`loser_key`,`loser_click_delta`,`loser_impression_delta`,`loser_position_delta`],templates:[`rank`,`direction`,`template`,`confidence`,`url_count`,`click_delta`,`impression_delta`,`movement_share`,`movement_share_scope`,`confidence_scope`,`eligible_rows`,`returned_rows`,`limited_rows`,`result_limit`,`source_possibly_truncated`,`common_terms`,`sample_urls`,`summary`],evidence:[`rank`,`evidence`],confounders:[`rank`,`source`,`title`,`date`,`scope`,`target`,`description`],segment:[`rank`,`dimension`,`data_status`,`evidence_scope`,`key`,`before_clicks`,`after_clicks`,`click_delta`,`before_impressions`,`after_impressions`,`impression_delta`,`before_position`,`after_position`,`position_delta`],unmatchedSegment:[`rank`,`dimension`,`data_status`,`key`,`retained_in`,`clicks`,`impressions`,`position`,`reason`]};function Dr(e,t){return[...e.output.segments[t].winners,...e.output.segments[t].losers].map((n,r)=>({rank:r+1,dimension:t,data_status:e.output.segments[t].dataStatus,evidence_scope:n.evidenceScope,key:n.key,before_clicks:n.beforeClicks,after_clicks:n.afterClicks,click_delta:n.clickDelta,before_impressions:n.beforeImpressions,after_impressions:n.afterImpressions,impression_delta:n.impressionDelta,before_position:n.beforePosition,after_position:n.afterPosition,position_delta:n.positionDelta}))}function Or(e,t){return e.output.segments[t].unmatchedSegments.map((n,r)=>({rank:r+1,dimension:t,data_status:e.output.segments[t].dataStatus,key:n.key,retained_in:n.retainedIn,clicks:n.clicks,impressions:n.impressions,position:n.position,reason:n.reason}))}function kr(e){return[{filename:`postmortem-summary.csv`,headers:[...S.summary],rows:[{workflow:e.workflow,site:e.site,generated_at:e.generatedAt,summary:e.summary,attribution:e.output.update.attribution,confidence:e.output.update.confidence,classification:e.output.update.classification,updates_matched:e.output.update.overlappingUpdates.length,known_confounders:e.output.update.confounders.length,page_segment_status:e.output.segments.page.dataStatus,page_segment_eligible_rows:e.output.segments.page.coverage.eligibleRows,page_segment_returned_rows:e.output.segments.page.coverage.returnedRows,page_segment_limited_rows:e.output.segments.page.coverage.limitedRows,page_segment_result_limit:e.output.segments.page.coverage.resultLimit,page_segment_source_row_limit:e.output.segments.page.coverage.sourceRowLimit,page_segment_source_possibly_truncated:e.output.segments.page.coverage.sourcePossiblyTruncated,page_segment_warnings:e.output.segments.page.warnings.join(`; `),query_segment_status:e.output.segments.query.dataStatus,query_segment_eligible_rows:e.output.segments.query.coverage.eligibleRows,query_segment_returned_rows:e.output.segments.query.coverage.returnedRows,query_segment_limited_rows:e.output.segments.query.coverage.limitedRows,query_segment_result_limit:e.output.segments.query.coverage.resultLimit,query_segment_source_row_limit:e.output.segments.query.coverage.sourceRowLimit,query_segment_source_possibly_truncated:e.output.segments.query.coverage.sourcePossiblyTruncated,query_segment_warnings:e.output.segments.query.warnings.join(`; `),device_segment_status:e.output.segments.device.dataStatus,device_segment_eligible_rows:e.output.segments.device.coverage.eligibleRows,device_segment_returned_rows:e.output.segments.device.coverage.returnedRows,device_segment_limited_rows:e.output.segments.device.coverage.limitedRows,device_segment_result_limit:e.output.segments.device.coverage.resultLimit,device_segment_source_row_limit:e.output.segments.device.coverage.sourceRowLimit,device_segment_source_possibly_truncated:e.output.segments.device.coverage.sourcePossiblyTruncated,device_segment_warnings:e.output.segments.device.warnings.join(`; `),country_segment_status:e.output.segments.country.dataStatus,country_segment_eligible_rows:e.output.segments.country.coverage.eligibleRows,country_segment_returned_rows:e.output.segments.country.coverage.returnedRows,country_segment_limited_rows:e.output.segments.country.coverage.limitedRows,country_segment_result_limit:e.output.segments.country.coverage.resultLimit,country_segment_source_row_limit:e.output.segments.country.coverage.sourceRowLimit,country_segment_source_possibly_truncated:e.output.segments.country.coverage.sourcePossiblyTruncated,country_segment_warnings:e.output.segments.country.warnings.join(`; `)}]},{filename:`workflow-steps.csv`,headers:[...S.steps],rows:e.steps.map((e,t)=>({rank:t+1,tool:e.tool,status:e.status,summary:e.summary}))},{filename:`workflow-actions.csv`,headers:[...S.actions],rows:e.actions.map((e,t)=>({rank:t+1,title:e.title,confidence:e.confidence,action:e.action}))},{filename:`postmortem-findings.csv`,headers:[...S.findings],rows:e.output.insights.map(e=>({dimension:e.dimension,data_status:e.dataStatus,eligible_rows:e.coverage.eligibleRows,returned_rows:e.coverage.returnedRows,limited_rows:e.coverage.limitedRows,result_limit:e.coverage.resultLimit,unmatched_rows:e.unmatchedRows,summary:e.summary,winner_key:e.winner?.key,winner_click_delta:e.winner?.clickDelta,winner_impression_delta:e.winner?.impressionDelta,winner_position_delta:e.winner?.positionDelta,loser_key:e.loser?.key,loser_click_delta:e.loser?.clickDelta,loser_impression_delta:e.loser?.impressionDelta,loser_position_delta:e.loser?.positionDelta}))},{filename:`postmortem-template-movement.csv`,headers:[...S.templates],rows:e.output.templateMovement.map((e,t)=>({rank:t+1,direction:e.direction,template:e.signature,confidence:e.confidence,url_count:e.urlCount,click_delta:e.clickDelta,impression_delta:e.impressionDelta,movement_share:e.movementShare,movement_share_scope:e.movementShareScope,confidence_scope:e.confidenceScope,eligible_rows:e.segmentCoverage.eligibleRows,returned_rows:e.segmentCoverage.returnedRows,limited_rows:e.segmentCoverage.limitedRows,result_limit:e.segmentCoverage.resultLimit,source_possibly_truncated:e.segmentCoverage.sourcePossiblyTruncated,common_terms:e.commonTerms.join(`; `),sample_urls:e.sampleUrls.join(`; `),summary:e.summary}))},{filename:`postmortem-update-evidence.csv`,headers:[...S.evidence],rows:e.output.update.evidence.map((e,t)=>({rank:t+1,evidence:e}))},{filename:`postmortem-confounders.csv`,headers:[...S.confounders],rows:e.output.update.confounders.map((e,t)=>({rank:t+1,source:e.source,title:e.title,date:e.date,scope:e.scope,target:e.target,description:e.description}))},...[`page`,`query`,`device`,`country`].map(t=>({filename:`postmortem-segment-${t}.csv`,headers:[...S.segment],rows:Dr(e,t)})),...[`page`,`query`,`device`,`country`].map(t=>({filename:`postmortem-segment-${t}-unmatched.csv`,headers:[...S.unmatchedSegment],rows:Or(e,t)}))]}function Ar(e){let t=e-Date.now();if(t<=0)return`expired`;let n=Math.round(t/6e4);if(n<60)return`in ${n}m`;let r=Math.floor(n/60),i=n%60;return i?`in ${r}h ${i}m`:`in ${r}h`}function jr(e,t){return{type:`boolean`,default:!0,description:e,negativeDescription:t}}function C(e){return typeof e==`string`?e:void 0}function w(e){return typeof e==`boolean`?e:void 0}function Mr(e){let t=C(e.rendering);if(t!==void 0&&t!==`auto`&&t!==`on`&&t!==`off`)throw new h(`INVALID_INPUT`,`--rendering must be auto, on, or off.`);if(w(e.js)===!0&&t&&t!==`on`)throw new h(`INVALID_INPUT`,`Use either --js or --rendering on, not both with different modes.`);return t??(w(e.js)?`on`:`auto`)}function Nr(e,t){let n=w(e[t]);if(n===!1)return!0;if(n===!0)return!1;let r=w(e[Pr(t)]);if(r===!1)return!0;if(r===!0)return!1;if(w(e[`no-${t}`])===!0||w(e[`no${Fr(t)}`])===!0)return!0}function Pr(e){return e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function Fr(e){let t=Pr(e);return t?`${t[0]?.toUpperCase()}${t.slice(1)}`:``}function T(e){if(typeof e==`number`)return e;if(typeof e!=`string`||!e.trim())return;let t=Number(e);return Number.isFinite(t)?t:void 0}function E(e,t){if(e===void 0||e===``)return;let n=T(e);if(n===void 0)throw new h(`INVALID_INPUT`,`${t} must be a number.`);return n}function D(e){if(typeof e!=`string`)return;let t=e.split(`,`).map(e=>e.trim()).filter(Boolean);return t.length?t:void 0}function Ir(e){return D(e)??[]}function Lr(e){let t={concurrency:T(e[`fetch-concurrency`]),intervalCap:T(e[`fetch-interval-cap`]),intervalMs:T(e[`fetch-interval-ms`])};return Object.values(t).some(e=>e!==void 0)?t:void 0}function O(e){return e.json===!0}async function Rr(e,t){let n=C(e),r=C(t);if(n&&r)throw Error(`Use either --body or --body-file, not both.`);if(!n&&!r)return;let i=n??await nr(r??``,`utf8`),a=JSON.parse(i);if(!a||typeof a!=`object`||Array.isArray(a))throw Error(`JSON body must be an object.`);return a}function k(e){if(e)return e;throw new h(`INVALID_INPUT`,"No site given. Pass --site with a domain, URL or sc-domain: property. Run `seo sites` to list your Search Console properties.")}async function zr(e,t={}){let n=k(e),r=ye((await dn(t.refresh,t.account)).map(e=>e.siteUrl),n);if(!r)throw new h(`PROPERTY_NOT_FOUND`,`This Google login has no Search Console property for ${n}. Run \`seo sites\` to list the properties it can read.`);return r}function Br(e){if(e)return e;throw new h(`INVALID_INPUT`,"No Google Analytics property given. Pass --property with the numeric property id. Run `seo analytics google properties` to list them.")}function Vr(e){if(typeof e==`number`)return Number.isFinite(e)?Math.round(e):void 0;if(!e)return;let t=Number.parseInt(e,10);return Number.isFinite(t)?t:void 0}function Hr(e={}){let t=e.env??process.env,n=Vr(e.columns)??Vr(e.streamColumns)??Vr(t.COLUMNS)??80;return Math.min(200,Math.max(40,n))}function A(e={}){let t=e.env??process.env,n=e.isTTY??!!process.stdout.isTTY,r=e.color??!!(n&&t.NO_COLOR===void 0);return{columns:Hr({...e,env:t,streamColumns:e.streamColumns??process.stdout.columns}),colors:vr.createColors(r),hasColor:r,isInteractive:n&&!t.CI}}function j(e){return yr(ar(e))}function Ur(e,t){let n=[],r=``;for(let i of e)r&&j(`${r}${i}`)>t?(n.push(r),r=i):r+=i;return r&&n.push(r),n}function Wr(e,t){if(!e)return[``];let n=e.trim().split(/\s+/u),r=[],i=``;for(let e of n){let n=j(e)>t?Ur(e,t):[e];for(let e of n)i?j(`${i} ${e}`)<=t?i+=` ${e}`:(r.push(i),i=e):i=e}return i&&r.push(i),r.length>0?r:[``]}function M(e,t){let n=Math.max(1,t);return e.replaceAll(`\r
|
|
3
|
+
import{$ as e,$n as t,$t as n,A as r,An as i,At as a,B as o,Bn as s,Bt as c,C as l,Cn as u,Ct as d,D as ee,Dn as te,Dt as f,E as ne,En as p,Et as m,F as re,Fn as ie,Ft as ae,G as oe,Gn as se,Gt as ce,H as le,Hn as ue,Ht as de,I as fe,In as pe,It as me,J as he,Jn as ge,Jt as _e,K as ve,Kn as ye,Kt as be,L as xe,Ln as Se,Lt as Ce,M as we,Mn as Te,Mt as Ee,N as De,Nn as Oe,Nt as ke,O as Ae,On as je,Ot as Me,P as Ne,Pn as Pe,Pt as Fe,Q as Ie,Qn as Le,Qt as Re,R as ze,Rn as Be,Rt as Ve,S as He,Sn as Ue,St as We,T as Ge,Tn as Ke,Tt as qe,U as Je,Un as Ye,Ut as Xe,V as Ze,Vn as Qe,Vt as $e,W as et,Wn as tt,Wt as nt,X as rt,Xn as h,Xt as it,Y as at,Yn as ot,Yt as st,Z as ct,Zn as lt,Zt as ut,_ as dt,_n as ft,_t as pt,a as mt,an as ht,at as gt,b as _t,bn as vt,bt as yt,c as bt,cn as xt,ct as St,d as Ct,dn as wt,dt as Tt,en as Et,er as Dt,et as Ot,f as kt,fn as At,ft as jt,g as Mt,gn as Nt,gt as Pt,h as Ft,hn as It,ht as Lt,i as Rt,in as zt,it as Bt,j as Vt,jn as Ht,jt as Ut,k as Wt,kn as Gt,kt as Kt,l as qt,ln as Jt,lt as Yt,m as Xt,mn as Zt,mt as Qt,nn as $t,nt as en,o as tn,on as nn,ot as rn,p as an,pn as on,pt as sn,q as cn,qn as ln,qt as un,rn as dn,rt as fn,sn as pn,st as mn,t as hn,tn as gn,tt as _n,u as vn,un as yn,ut as bn,v as xn,vn as Sn,vt as Cn,w as wn,wn as Tn,wt as En,x as Dn,xn as On,xt as kn,y as An,yn as jn,yt as Mn,z as Nn,zn as Pn,zt as Fn}from"./dist-U5Io-lSG.js";import{arch as In,homedir as Ln,platform as Rn}from"node:os";import{basename as zn,dirname as Bn,join as g,posix as Vn,resolve as Hn,win32 as Un}from"node:path";import{constants as Wn,copyFileSync as Gn,createWriteStream as Kn,existsSync as _,mkdirSync as qn,readFileSync as Jn,readdirSync as Yn,realpathSync as Xn,renameSync as Zn,statSync as Qn,writeFileSync as $n}from"node:fs";import{fileURLToPath as er}from"node:url";import{mkdir as tr,readFile as nr,writeFile as rr}from"node:fs/promises";import{isDeepStrictEqual as ir,stripVTControlCharacters as ar}from"node:util";import{spawn as or,spawnSync as sr}from"node:child_process";import{defineCommand as v,runCommand as cr,runMain as lr}from"citty";import{cancel as ur,confirm as dr,intro as y,isCancel as fr,log as pr,multiselect as mr,note as b,outro as x,password as hr,select as gr,text as _r}from"@clack/prompts";import vr from"picocolors";import yr from"string-width";import br from"cli-table3";import{finished as xr}from"node:stream/promises";import{applyEdits as Sr,modify as Cr,parse as wr,printParseErrorCode as Tr}from"jsonc-parser";import Er from"update-notifier";const S={summary:`workflow.site.generated_at.summary.attribution.confidence.classification.updates_matched.known_confounders.page_segment_status.page_segment_eligible_rows.page_segment_returned_rows.page_segment_limited_rows.page_segment_result_limit.page_segment_source_row_limit.page_segment_source_possibly_truncated.page_segment_warnings.query_segment_status.query_segment_eligible_rows.query_segment_returned_rows.query_segment_limited_rows.query_segment_result_limit.query_segment_source_row_limit.query_segment_source_possibly_truncated.query_segment_warnings.device_segment_status.device_segment_eligible_rows.device_segment_returned_rows.device_segment_limited_rows.device_segment_result_limit.device_segment_source_row_limit.device_segment_source_possibly_truncated.device_segment_warnings.country_segment_status.country_segment_eligible_rows.country_segment_returned_rows.country_segment_limited_rows.country_segment_result_limit.country_segment_source_row_limit.country_segment_source_possibly_truncated.country_segment_warnings`.split(`.`),steps:[`rank`,`tool`,`status`,`summary`],actions:[`rank`,`title`,`confidence`,`action`],findings:[`dimension`,`data_status`,`eligible_rows`,`returned_rows`,`limited_rows`,`result_limit`,`unmatched_rows`,`summary`,`winner_key`,`winner_click_delta`,`winner_impression_delta`,`winner_position_delta`,`loser_key`,`loser_click_delta`,`loser_impression_delta`,`loser_position_delta`],templates:[`rank`,`direction`,`template`,`confidence`,`url_count`,`click_delta`,`impression_delta`,`movement_share`,`movement_share_scope`,`confidence_scope`,`eligible_rows`,`returned_rows`,`limited_rows`,`result_limit`,`source_possibly_truncated`,`common_terms`,`sample_urls`,`summary`],evidence:[`rank`,`evidence`],confounders:[`rank`,`source`,`title`,`date`,`scope`,`target`,`description`],segment:[`rank`,`dimension`,`data_status`,`evidence_scope`,`key`,`before_clicks`,`after_clicks`,`click_delta`,`before_impressions`,`after_impressions`,`impression_delta`,`before_position`,`after_position`,`position_delta`],unmatchedSegment:[`rank`,`dimension`,`data_status`,`key`,`retained_in`,`clicks`,`impressions`,`position`,`reason`]};function Dr(e,t){return[...e.output.segments[t].winners,...e.output.segments[t].losers].map((n,r)=>({rank:r+1,dimension:t,data_status:e.output.segments[t].dataStatus,evidence_scope:n.evidenceScope,key:n.key,before_clicks:n.beforeClicks,after_clicks:n.afterClicks,click_delta:n.clickDelta,before_impressions:n.beforeImpressions,after_impressions:n.afterImpressions,impression_delta:n.impressionDelta,before_position:n.beforePosition,after_position:n.afterPosition,position_delta:n.positionDelta}))}function Or(e,t){return e.output.segments[t].unmatchedSegments.map((n,r)=>({rank:r+1,dimension:t,data_status:e.output.segments[t].dataStatus,key:n.key,retained_in:n.retainedIn,clicks:n.clicks,impressions:n.impressions,position:n.position,reason:n.reason}))}function kr(e){return[{filename:`postmortem-summary.csv`,headers:[...S.summary],rows:[{workflow:e.workflow,site:e.site,generated_at:e.generatedAt,summary:e.summary,attribution:e.output.update.attribution,confidence:e.output.update.confidence,classification:e.output.update.classification,updates_matched:e.output.update.overlappingUpdates.length,known_confounders:e.output.update.confounders.length,page_segment_status:e.output.segments.page.dataStatus,page_segment_eligible_rows:e.output.segments.page.coverage.eligibleRows,page_segment_returned_rows:e.output.segments.page.coverage.returnedRows,page_segment_limited_rows:e.output.segments.page.coverage.limitedRows,page_segment_result_limit:e.output.segments.page.coverage.resultLimit,page_segment_source_row_limit:e.output.segments.page.coverage.sourceRowLimit,page_segment_source_possibly_truncated:e.output.segments.page.coverage.sourcePossiblyTruncated,page_segment_warnings:e.output.segments.page.warnings.join(`; `),query_segment_status:e.output.segments.query.dataStatus,query_segment_eligible_rows:e.output.segments.query.coverage.eligibleRows,query_segment_returned_rows:e.output.segments.query.coverage.returnedRows,query_segment_limited_rows:e.output.segments.query.coverage.limitedRows,query_segment_result_limit:e.output.segments.query.coverage.resultLimit,query_segment_source_row_limit:e.output.segments.query.coverage.sourceRowLimit,query_segment_source_possibly_truncated:e.output.segments.query.coverage.sourcePossiblyTruncated,query_segment_warnings:e.output.segments.query.warnings.join(`; `),device_segment_status:e.output.segments.device.dataStatus,device_segment_eligible_rows:e.output.segments.device.coverage.eligibleRows,device_segment_returned_rows:e.output.segments.device.coverage.returnedRows,device_segment_limited_rows:e.output.segments.device.coverage.limitedRows,device_segment_result_limit:e.output.segments.device.coverage.resultLimit,device_segment_source_row_limit:e.output.segments.device.coverage.sourceRowLimit,device_segment_source_possibly_truncated:e.output.segments.device.coverage.sourcePossiblyTruncated,device_segment_warnings:e.output.segments.device.warnings.join(`; `),country_segment_status:e.output.segments.country.dataStatus,country_segment_eligible_rows:e.output.segments.country.coverage.eligibleRows,country_segment_returned_rows:e.output.segments.country.coverage.returnedRows,country_segment_limited_rows:e.output.segments.country.coverage.limitedRows,country_segment_result_limit:e.output.segments.country.coverage.resultLimit,country_segment_source_row_limit:e.output.segments.country.coverage.sourceRowLimit,country_segment_source_possibly_truncated:e.output.segments.country.coverage.sourcePossiblyTruncated,country_segment_warnings:e.output.segments.country.warnings.join(`; `)}]},{filename:`workflow-steps.csv`,headers:[...S.steps],rows:e.steps.map((e,t)=>({rank:t+1,tool:e.tool,status:e.status,summary:e.summary}))},{filename:`workflow-actions.csv`,headers:[...S.actions],rows:e.actions.map((e,t)=>({rank:t+1,title:e.title,confidence:e.confidence,action:e.action}))},{filename:`postmortem-findings.csv`,headers:[...S.findings],rows:e.output.insights.map(e=>({dimension:e.dimension,data_status:e.dataStatus,eligible_rows:e.coverage.eligibleRows,returned_rows:e.coverage.returnedRows,limited_rows:e.coverage.limitedRows,result_limit:e.coverage.resultLimit,unmatched_rows:e.unmatchedRows,summary:e.summary,winner_key:e.winner?.key,winner_click_delta:e.winner?.clickDelta,winner_impression_delta:e.winner?.impressionDelta,winner_position_delta:e.winner?.positionDelta,loser_key:e.loser?.key,loser_click_delta:e.loser?.clickDelta,loser_impression_delta:e.loser?.impressionDelta,loser_position_delta:e.loser?.positionDelta}))},{filename:`postmortem-template-movement.csv`,headers:[...S.templates],rows:e.output.templateMovement.map((e,t)=>({rank:t+1,direction:e.direction,template:e.signature,confidence:e.confidence,url_count:e.urlCount,click_delta:e.clickDelta,impression_delta:e.impressionDelta,movement_share:e.movementShare,movement_share_scope:e.movementShareScope,confidence_scope:e.confidenceScope,eligible_rows:e.segmentCoverage.eligibleRows,returned_rows:e.segmentCoverage.returnedRows,limited_rows:e.segmentCoverage.limitedRows,result_limit:e.segmentCoverage.resultLimit,source_possibly_truncated:e.segmentCoverage.sourcePossiblyTruncated,common_terms:e.commonTerms.join(`; `),sample_urls:e.sampleUrls.join(`; `),summary:e.summary}))},{filename:`postmortem-update-evidence.csv`,headers:[...S.evidence],rows:e.output.update.evidence.map((e,t)=>({rank:t+1,evidence:e}))},{filename:`postmortem-confounders.csv`,headers:[...S.confounders],rows:e.output.update.confounders.map((e,t)=>({rank:t+1,source:e.source,title:e.title,date:e.date,scope:e.scope,target:e.target,description:e.description}))},...[`page`,`query`,`device`,`country`].map(t=>({filename:`postmortem-segment-${t}.csv`,headers:[...S.segment],rows:Dr(e,t)})),...[`page`,`query`,`device`,`country`].map(t=>({filename:`postmortem-segment-${t}-unmatched.csv`,headers:[...S.unmatchedSegment],rows:Or(e,t)}))]}function Ar(e){let t=e-Date.now();if(t<=0)return`expired`;let n=Math.round(t/6e4);if(n<60)return`in ${n}m`;let r=Math.floor(n/60),i=n%60;return i?`in ${r}h ${i}m`:`in ${r}h`}function jr(e,t){return{type:`boolean`,default:!0,description:e,negativeDescription:t}}function C(e){return typeof e==`string`?e:void 0}function w(e){return typeof e==`boolean`?e:void 0}function Mr(e){let t=C(e.rendering);if(t!==void 0&&t!==`auto`&&t!==`on`&&t!==`off`)throw new h(`INVALID_INPUT`,`--rendering must be auto, on, or off.`);if(w(e.js)===!0&&t&&t!==`on`)throw new h(`INVALID_INPUT`,`Use either --js or --rendering on, not both with different modes.`);return t??(w(e.js)?`on`:`auto`)}function Nr(e,t){let n=w(e[t]);if(n===!1)return!0;if(n===!0)return!1;let r=w(e[Pr(t)]);if(r===!1)return!0;if(r===!0)return!1;if(w(e[`no-${t}`])===!0||w(e[`no${Fr(t)}`])===!0)return!0}function Pr(e){return e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function Fr(e){let t=Pr(e);return t?`${t[0]?.toUpperCase()}${t.slice(1)}`:``}function T(e){if(typeof e==`number`)return e;if(typeof e!=`string`||!e.trim())return;let t=Number(e);return Number.isFinite(t)?t:void 0}function E(e,t){if(e===void 0||e===``)return;let n=T(e);if(n===void 0)throw new h(`INVALID_INPUT`,`${t} must be a number.`);return n}function D(e){if(typeof e!=`string`)return;let t=e.split(`,`).map(e=>e.trim()).filter(Boolean);return t.length?t:void 0}function Ir(e){return D(e)??[]}function Lr(e){let t={concurrency:T(e[`fetch-concurrency`]),intervalCap:T(e[`fetch-interval-cap`]),intervalMs:T(e[`fetch-interval-ms`])};return Object.values(t).some(e=>e!==void 0)?t:void 0}function O(e){return e.json===!0}async function Rr(e,t){let n=C(e),r=C(t);if(n&&r)throw Error(`Use either --body or --body-file, not both.`);if(!n&&!r)return;let i=n??await nr(r??``,`utf8`),a=JSON.parse(i);if(!a||typeof a!=`object`||Array.isArray(a))throw Error(`JSON body must be an object.`);return a}function k(e){if(e)return e;throw new h(`INVALID_INPUT`,"No site given. Pass --site with a domain, URL or sc-domain: property. Run `seo sites` to list your Search Console properties.")}async function zr(e,t={}){let n=k(e),r=ye((await dn(t.refresh,t.account)).map(e=>e.siteUrl),n);if(!r)throw new h(`PROPERTY_NOT_FOUND`,`This Google login has no Search Console property for ${n}. Run \`seo sites\` to list the properties it can read.`);return r}function Br(e){if(e)return e;throw new h(`INVALID_INPUT`,"No Google Analytics property given. Pass --property with the numeric property id. Run `seo analytics google properties` to list them.")}function Vr(e){if(typeof e==`number`)return Number.isFinite(e)?Math.round(e):void 0;if(!e)return;let t=Number.parseInt(e,10);return Number.isFinite(t)?t:void 0}function Hr(e={}){let t=e.env??process.env,n=Vr(e.columns)??Vr(e.streamColumns)??Vr(t.COLUMNS)??80;return Math.min(200,Math.max(40,n))}function A(e={}){let t=e.env??process.env,n=e.isTTY??!!process.stdout.isTTY,r=e.color??!!(n&&t.NO_COLOR===void 0);return{columns:Hr({...e,env:t,streamColumns:e.streamColumns??process.stdout.columns}),colors:vr.createColors(r),hasColor:r,isInteractive:n&&!t.CI}}function j(e){return yr(ar(e))}function Ur(e,t){let n=[],r=``;for(let i of e)r&&j(`${r}${i}`)>t?(n.push(r),r=i):r+=i;return r&&n.push(r),n}function Wr(e,t){if(!e)return[``];let n=e.trim().split(/\s+/u),r=[],i=``;for(let e of n){let n=j(e)>t?Ur(e,t):[e];for(let e of n)i?j(`${i} ${e}`)<=t?i+=` ${e}`:(r.push(i),i=e):i=e}return i&&r.push(i),r.length>0?r:[``]}function M(e,t){let n=Math.max(1,t);return e.replaceAll(`\r
|
|
4
4
|
`,`
|
|
5
5
|
`).split(`
|
|
6
6
|
`).flatMap(e=>Wr(e,n))}function Gr(e,t){if(j(e)<=t)return e;let n=Math.max(1,t-j(`...`)),r=``;for(let t of e){if(j(`${r}${t}`)>n)break;r+=t}return`${r}...`}const Kr={top:``,"top-mid":``,"top-left":``,"top-right":``,bottom:``,"bottom-mid":``,"bottom-left":``,"bottom-right":``,left:``,"left-mid":``,mid:``,"mid-mid":``,right:``,"right-mid":``,middle:``};function qr(e){return e===void 0?``:String(e)}function Jr(e,t){return e.map((e,n)=>{let r=t.map(e=>qr(e[n]));return Math.min(42,Math.max(j(e),...r.map(j),4))})}function Yr(e,t,n){return e.length===0||e.length>4||!e.map((e,n)=>t.every(e=>/^-?(?:\d+(?:\.\d+)?|\d+(?:\.\d+)?%)$/u.test(qr(e[n]).trim()))).some(Boolean)?!1:Jr(e,t).reduce((e,t)=>e+t+2,0)<=n.columns}function Xr(e,t,n){if(!/(?:status|state|assessment|data|allowed)/iu.test(e))return t;let r=t.trim().toLowerCase();return[`pass`,`passed`,`completed`,`allowed`,`yes`].includes(r)?n.colors.green(t):[`warn`,`warning`,`review`,`partial`].includes(r)?n.colors.yellow(t):[`fail`,`failed`,`blocked`,`no`].includes(r)?n.colors.red(t):[`unknown`,`unavailable`].includes(r)?n.colors.blue(t):t}function Zr(e,t,n){let r=Jr(e,t).map(e=>e+2),i=new br({chars:Kr,colWidths:r,head:e.map(e=>n.colors.bold(e)),style:{border:[],head:[],"padding-left":0,"padding-right":2},wordWrap:!1});for(let a of t)i.push(e.map((e,t)=>M(Xr(e,qr(a[t]),n),Math.max(1,(r[t]??3)-2)).join(`
|
|
@@ -57,7 +57,7 @@ Updates
|
|
|
57
57
|
`),`Setup will`),b(Uo.join(`
|
|
58
58
|
`),`Then run`),x(`Dry run complete. Nothing was changed.`));return}tt();let n=N({json:t}),r=await Lo({interactive:n})??await Bo({interactive:n}),i=n?await Ho():[],a=n?await Vo():{status:`skipped`};if(t){P({auth:r,mcp:i,skill:a,next:Uo});return}F([[`Sign-in`,Go(r)],[`MCP server`,qo(i)],[`SEO skill`,Ko(a)]]);let o=i.filter(e=>e.error);o.length&&b(o.map(e=>`${e.client}: ${e.error}`).join(`
|
|
59
59
|
`),`MCP setup skipped`),a.error&&b(a.error,`SEO skill install failed`),b([`seo sites list your Search Console properties`,`seo report --site <site> run the main report for one of them`].join(`
|
|
60
|
-
`),`Try next`),x(`Setup complete.`),Jo()}const Xo=v({meta:{name:`setup`,description:`Sign in with Google, then add the MCP server and skill`},args:{"dry-run":{type:`boolean`,default:!1,description:`Show what setup does without changing anything.`},json:{type:`boolean`,default:!1,description:`Print machine-readable JSON. Never prompts.`}},run:async({args:e})=>Yo(e)}),Zo=v({...Xo,meta:{name:`start`,description:`Start here: sign in with Google, then add the MCP server and skill to your agents`}}),Qo=v({...Zo,meta:{name:`init`,description:"Legacy alias for `seo start`."}}),$o=v({meta:{name:`logs`,description:`Manage local log retention`},subCommands:{prune:v({meta:{name:`prune`,description:`Rotate large logs and remove old local logs`},args:{quiet:{type:`boolean`,default:!1,description:`Do not print a result.`},json:{type:`boolean`,default:!1,description:`Print machine-readable JSON.`}},run:async({args:e})=>{let t=He();if(O(e)){P(t);return}e.quiet||process.stdout.write(`Rotated ${t.rotated} and removed ${t.removed} log files. ${Ai(t.sizeBytes)} retained.\n`)}})}}),es=[{client:`claude-desktop`,flag:`claude-desktop`},{client:`claude-code`,flag:`claude-code`},{client:`codex`,flag:`codex`},{client:`cursor`,flag:`cursor`}];function ts(e,t){return w(e.all)?t:es.filter(({flag:t})=>w(e[t])).map(({client:e})=>e)}const ns=v({meta:{name:`mcp`,description:`MCP server helpers`},subCommands:{serve:v({meta:{name:`serve`,description:`Run the SEO MCP server`},args:{test:{type:`boolean`,default:!1,description:`Start in test mode`}},run:async({args:e})=>{let{startMcpServer:t}=await import(`./dist-
|
|
60
|
+
`),`Try next`),x(`Setup complete.`),Jo()}const Xo=v({meta:{name:`setup`,description:`Sign in with Google, then add the MCP server and skill`},args:{"dry-run":{type:`boolean`,default:!1,description:`Show what setup does without changing anything.`},json:{type:`boolean`,default:!1,description:`Print machine-readable JSON. Never prompts.`}},run:async({args:e})=>Yo(e)}),Zo=v({...Xo,meta:{name:`start`,description:`Start here: sign in with Google, then add the MCP server and skill to your agents`}}),Qo=v({...Zo,meta:{name:`init`,description:"Legacy alias for `seo start`."}}),$o=v({meta:{name:`logs`,description:`Manage local log retention`},subCommands:{prune:v({meta:{name:`prune`,description:`Rotate large logs and remove old local logs`},args:{quiet:{type:`boolean`,default:!1,description:`Do not print a result.`},json:{type:`boolean`,default:!1,description:`Print machine-readable JSON.`}},run:async({args:e})=>{let t=He();if(O(e)){P(t);return}e.quiet||process.stdout.write(`Rotated ${t.rotated} and removed ${t.removed} log files. ${Ai(t.sizeBytes)} retained.\n`)}})}}),es=[{client:`claude-desktop`,flag:`claude-desktop`},{client:`claude-code`,flag:`claude-code`},{client:`codex`,flag:`codex`},{client:`cursor`,flag:`cursor`}];function ts(e,t){return w(e.all)?t:es.filter(({flag:t})=>w(e[t])).map(({client:e})=>e)}const ns=v({meta:{name:`mcp`,description:`MCP server helpers`},subCommands:{serve:v({meta:{name:`serve`,description:`Run the SEO MCP server`},args:{test:{type:`boolean`,default:!1,description:`Start in test mode`}},run:async({args:e})=>{let{startMcpServer:t}=await import(`./dist-GOZ_hkEB.js`);await t({test:w(e.test)})}}),install:v({meta:{name:`install`,description:`Install or remove SEO MCP config for local clients`},args:{uninstall:{type:`boolean`,default:!1,description:`Remove the SEO MCP config instead of adding it`},reinstall:{type:`boolean`,default:!1,description:`Rewrite an existing managed SEO MCP config`},"claude-desktop":{type:`boolean`,default:!1,description:`Update Claude Desktop`},"claude-code":{type:`boolean`,default:!1,description:`Update Claude Code`},codex:{type:`boolean`,default:!1,description:`Update Codex CLI, app, and IDE extension`},cursor:{type:`boolean`,default:!1,description:`Update Cursor`},all:{type:`boolean`,default:!1,description:`Update every detected MCP client`},json:{type:`boolean`,default:!1,description:`Print structured JSON output`}},run:async({args:e})=>{if(w(e.uninstall)&&w(e.reinstall))throw new h(`INVALID_INPUT`,`Use either --uninstall or --reinstall, not both.`);let t=$a(),n=no({targets:t}),r=O(e),i=ts(e,n.map(e=>e.client));if(i.length===0){if(!N({json:r}))throw new h(`INVALID_INPUT`,`Choose an MCP client with --claude-desktop, --claude-code, --codex, --cursor, or --all.`);let a=n.length>0?n:t;i=L(await mr({message:e.uninstall?`Remove seo from which MCP clients?`:`Install seo into which MCP clients?`,options:a.map(e=>({value:e.client,label:e.label,hint:e.path})),initialValues:n.map(e=>e.client),required:!0}))}let a=i.filter(e=>!t.some(t=>t.client===e));if(a.length>0)throw new h(`INVALID_INPUT`,`MCP setup is not supported for ${a.join(`, `)} on ${process.platform}.`);let o=t.filter(e=>i.includes(e.client)).map(t=>w(e.uninstall)?So(t):xo(t,{reinstall:w(e.reinstall)}));if(r){P({operation:w(e.uninstall)?`uninstall`:`install`,results:o});return}for(let e of o)process.stdout.write(`${e.changed?`updated`:`skipped`} ${e.client} · ${e.path}\n`)}})}}),rs=v({meta:{name:`index-coverage`,description:`Find crawlable pages that deserve a closer Google index check`},args:{site:{type:`string`,description:`GSC property URL, for example sc-domain:example.com.`},url:{type:`string`,description:`Start URL to crawl. Defaults to the home page.`},sitemaps:{type:`string`,description:`Comma-separated XML sitemap URLs. Defaults to declarations captured by the crawl.`},days:{type:`string`,description:`Finalized Search Console date range. Defaults to 90 days.`},"row-limit":{type:`string`,description:`Maximum Search Console page rows. Defaults to 100000.`},"max-sitemap-urls":{type:`string`,description:`Maximum sitemap inventory URLs. Defaults to 100000.`},limit:{type:`string`,description:`Maximum URLs returned in each evidence group. Defaults to 100.`},refresh:{type:`boolean`,default:!1,description:`Bypass the local Search Console cache.`},json:{type:`boolean`,default:!1,description:`Print machine-readable JSON.`}},run:async({args:e})=>{let t=O(e),n=k(C(e.site)),r=Ir(e.sitemaps),i=await kn({site:n,url:C(e.url),sitemaps:r.length?r:void 0,days:T(e.days),rowLimit:T(e[`row-limit`]),maxSitemapUrls:T(e[`max-sitemap-urls`]),itemsPerSection:T(e.limit),refresh:w(e.refresh)});if(t){P(i);return}K({title:`Index coverage`,target:i.site,status:i.sources.crawl.completeness===`complete`&&i.sources.searchConsole.completeness===`complete`?i.summary.crawlableCandidatesWithoutRetainedSearchVisibility>0?`warning`:`pass`:`unknown`,summary:`${i.summary.crawlableCandidatesWithoutRetainedSearchVisibility} crawlable pages need URL Inspection review.`,metrics:[{label:`Crawl report`,value:i.input.crawlReport.id},{label:`Crawl evidence`,value:i.sources.crawl.completeness},{label:`Sitemap evidence`,value:i.sources.sitemap.completeness},{label:`Search evidence`,value:i.sources.searchConsole.completeness},{label:`Search window`,value:`${i.sources.searchConsole.startDate} to ${i.sources.searchConsole.endDate}`},{label:`Search-visible pages`,value:i.summary.retainedSearchVisibleUrls},{label:`Blocked/non-indexable`,value:i.summary.blockedOrNonIndexableCrawlUrls},{label:`Sitemap only`,value:i.summary.sitemapOnlyUrls},{label:`Search Console only`,value:i.summary.searchConsoleOnlyUrls}]}),i.crawlableWithoutRetainedSearchVisibility.items.length&&(process.stdout.write(`
|
|
61
61
|
Representative URL Inspection candidates
|
|
62
62
|
`),I([`URL`,`Status`,`In sitemap`],i.crawlableWithoutRetainedSearchVisibility.items.map(e=>[G(e.url,80),e.status,e.inSitemap?`yes`:`no`]))),Y(`How to read this report`,i.caveats)}}),is=v({meta:{name:`link-recover`,description:`Find search-value URLs that are now broken, blocked, or poorly redirected`},args:{site:{type:`string`},...X([`days`,`limit`,`minImpressions`,`refresh`,`js`],{days:{description:`GSC lookback window. Defaults to 90.`},limit:{description:`Maximum GSC pages to check. Defaults to 50.`},minImpressions:{description:`Minimum impressions to check a page. Defaults to 100.`},refresh:{description:`Bypass local GSC and HTTP caches.`},js:{description:`Force JavaScript rendering for final page extraction.`}}),"min-clicks":{type:`string`,description:`Minimum clicks to check a page. Defaults to 1.`},json:{type:`boolean`,default:!1,description:`Print machine-readable JSON.`}},run:async({args:e})=>{let t=O(e),n=await Mn({site:k(C(e.site)),days:T(e.days),limit:T(e.limit),minClicks:T(e[`min-clicks`]),minImpressions:T(e[`min-impressions`]),refresh:w(e.refresh),js:w(e.js)?!0:`auto`});if(t){P(n);return}K({title:`Link recovery`,target:n.site,status:n.warnings.length>0?`unknown`:n.summary.recoverable>0?`warning`:`pass`,summary:n.summary.recoverable>0?`${H(n.summary.recoverable)} previously visible URLs need recovery review.`:`No recoverable URLs were found in the retained evidence.`,metrics:[{label:`Range`,value:`${n.range.startDate} to ${n.range.endDate}`},{label:`Checked`,value:H(n.summary.checked)},{label:`Recoverable`,value:H(n.summary.recoverable)},{label:`High severity`,value:H(n.summary.high)},{label:`Clicks at risk`,value:H(n.summary.clicksAtRisk)},{label:`Impressions at risk`,value:H(n.summary.impressionsAtRisk)}]}),n.items.length&&(q([`Severity`,`Issue`,`Clicks`,`Impr`,`URL`,`Action`],n.items.map(e=>[e.severity,e.issue,H(e.clicks),H(e.impressions),G(e.url,56),G(e.recommendation.action,72)])),J(`Top recovery actions`,n.items.map(e=>({label:G(e.url,96),context:`${e.severity}, ${H(e.clicks)} clicks at risk`,action:e.recommendation.action})))),Y(`Warnings`,n.warnings.slice(0,10))}}),as=v({meta:{name:`redirect-trace`,description:`Trace redirects and report final indexability/canonical issues`},args:{url:{type:`string`,required:!0,description:`URL to trace.`},"max-hops":{type:`string`,description:`Maximum redirect hops to follow. Defaults to 10.`},refresh:{type:`boolean`,default:!1,description:`Bypass local HTTP cache for final page extraction.`},js:{type:`boolean`,default:!1,description:`Force JavaScript rendering for final page extraction.`},json:{type:`boolean`,default:!1,description:`Print machine-readable JSON.`}},run:async({args:e})=>{let t=await yt({url:C(e.url)??``,maxHops:T(e[`max-hops`]),refresh:w(e.refresh),js:w(e.js)?!0:`auto`});if(O(e)){P(t);return}K({title:`Redirect trace`,target:t.url,status:t.summary.issues.length>0?`warning`:t.summary.finalIndexable===void 0?`unknown`:`pass`,summary:t.summary.issues.length>0?t.summary.issues.join(`, `):`${t.summary.hops} redirect hops ended at HTTP ${t.summary.finalStatus}.`,metrics:[{label:`Final URL`,value:t.finalUrl},{label:`Final status`,value:t.summary.finalStatus},{label:`Indexable`,value:t.summary.finalIndexable===void 0?`Unknown`:t.summary.finalIndexable?`Yes`:`No`},{label:`Hops`,value:t.summary.hops}]}),I([`#`,`Status`,`URL`,`Next`],t.chain.map((e,t)=>[t+1,e.status,G(e.url,72),G(e.nextUrl??`-`,72)])),t.finalPage&&(process.stdout.write(`
|
|
63
63
|
Final page
|
|
@@ -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-U5Io-lSG.js";export{e as startMcpServer};
|