@seoagent-official/seoagent 1.92.0 → 1.93.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +1 -1
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -821,7 +821,7 @@ skill knows what to do.
821
821
  `),corrections:a}}var Ag=/^\s*(?:$|[()[\]{}.,;:!?'"’”…]|—|–|→|\btags?\b|\belements?\b|\bmeta\b|\bmarkup\b|\bstructured\b|\bdata\b|\bcards?\b|\blinks?\b|\burls?\b|\bdeclarations?\b|\bsnippets?\b|\battributes?\b|\bentr(?:y|ies)\b|\brel\b|\bhref\b|\bschema\b|\bjson[\s-]*ld\b|\bis\b|\bare\b|\bwas\b|\bwere\b|\bisn['’]?t\b|\baren['’]?t\b|\bwasn['’]?t\b|\bweren['’]?t\b|\bdid\b|\bdidn['’]?t\b|\bdoes\b|\bdoesn['’]?t\b|\bha[sd]\b|\bhasn['’]?t\b|\bhadn['’]?t\b|\bnot\b|\bnever\b|\bpresent\b|\bfound\b|\bexists?\b|\bexisted\b|\bset\b|\bdefined\b|\bconfigured\b|\bmissing\b|\babsent\b|\banywhere\b|\bat\s+all\b|\byet\b|\bto\b|\bon\b|\bfor\b|\bin\b|\binto\b|\bacross\b|\bat\b|\bvia\b|\bwith\b|\band\b|\bor\b|\bplus\b|\bper\b|https?:|\/|`)/i,Pg=/\b(?:add(?:ed|ing|s)?|implement(?:ed|ing|s)?|inject(?:ed|ing|s)?|creat(?:e|ed|ing|es)|introduc(?:e|ed|ing|es))\s+(?:[\w`'’"/-]+\s+){0,3}$/i,Ig=/\b(?:no|not|missing|absent|without|zero|lack(?:s|ed|ing)?|ha[sd]\s+no|have\s+no|never\s+(?:had|served|shipped)|(?:do|does|did)\s*(?:n['’]t|\s+not)?\s+(?:have|serve|include|ship|set|emit|render|output)|don['’]t\s+(?:have|serve|include|ship|set|emit|render|output))\s+(?:(?:a|an|the|any|its|valid|proper|correct|self-referencing)\s+){0,2}$/i,La=/^\s*[:,(]?\s*(?:tags?|elements?|meta|markup|data|cards?|links?|urls?|declarations?|snippets?|attributes?)?\s*(?:(?:is|are|was|were|ha[sd])\s+)?(?:still\s+)?(?:missing|absent|nowhere|not\s+(?:previously\s+)?(?:present|set|defined|found|served|rendered|emitted)|never\s+(?:previously\s+)?existed|did\s*n(?:ot|['’]?t)\s+(?:previously\s+)?(?:exist|have)|does\s*n(?:ot|['’]?t)\s+(?:currently\s+)?(?:exist|have)|no\s+longer\s+exists?)\b/i,Og=/^\s*[:,(]?\s*(?:tags?|elements?|meta|markup|data|cards?|links?|schema)?\s*(?:is|are|was|were|do|does|did|would|will|can|could|should|must)\s*n(?:ot|['’]t)\b/i;function Na(e,t,n){let r=e.slice(t+n.length),o=e.slice(Math.max(0,t-64),t);return!Ag.test(r)||!La.test(r)&&Og.test(r)?!1:Pg.test(o)||Ig.test(o)||La.test(r)}function Ba(e){let t=`~~ \u2192 ${cn}:`;if(!e.includes(t))return{text:e,stripped:0};let n=e.split(`
822
822
  `),r=0;for(let o=0;o<n.length;o++){let i=n[o].indexOf(t);if(i===-1)continue;let s=n[o].slice(0,i),a=s.indexOf("~~");a!==-1&&(n[o]=s.slice(0,a)+s.slice(a+2),r++)}return{text:n.join(`
823
823
  `),stripped:r}}var Tg=an.join(b,"audit","evidence.md");function ja(e){let t=e.split(Ma).join("/");return t===Tg||t===an.join(b,"audit","findings.md")||t===an.join(b,"pages.md")||t===an.join(b,"keywords.md")||t.startsWith(an.join(b,"inbox")+"/")}function Da(e){return e.split(Ma).join("/").split("/").includes(".claude")}function Ha(e,t=[]){let n;try{n=sg(e)}catch{return t}for(let r of n){let o=So(e,r),i;try{i=ag(o)}catch{continue}i.isDirectory()?Ha(o,t):r.endsWith(".md")&&t.push(o)}return t}function At(e,t={}){let n=So(e,b,"audit","evidence.md"),r={evidenceFound:Ra(n),evidencePath:n,sourceRender:!1,scanned:[],skipped:[],corrections:[]};if(!r.evidenceFound)return r;let o=Ca(n,"utf-8");if(ar(o))return r.sourceRender=!0,r;let i=new Map;for(let s of Ha(So(e,b))){let a=Ea(e,s);ja(a)||Da(a)||i.set(Aa(s),a)}for(let s of t.extraFiles??[]){let a=Aa(e,s),l=Ea(e,a);if(ja(l)||Da(l)){r.skipped.push(l);continue}Ra(a)?i.set(a,l):r.skipped.push(l)}for(let[s,a]of i){let l;try{l=Ca(s,"utf-8")}catch{continue}r.scanned.push(a);let{text:c,corrections:d}=Eg(l,o,{filePath:a});if(d.length>0){lg(s,c,"utf-8");for(let f of d)r.corrections.push({...f,file:a})}}return r}function Ya(e){if(typeof e!="string")return{force:e===!0};let t=e.trim().replace(/\\/g,"/").replace(/^\.?\/+/,"").replace(/^\.seoagent\//,"").replace(/^\/+/,"");return t?{force:!1,forcePaths:[t]}:{force:!0}}function Wa(e){return"sha256:"+Ka("sha256").update(e).digest("hex")}function ue(e){return Ka("sha256").update(e,"utf-8").digest("hex")}function Fg(e,t,n={}){let r=[],o=i=>n.force===!0||n.forcePaths?.includes(i)===!0;for(let i of e.artifacts){let s=t[i.path]??{exists:!1,locallyEdited:!1};if(!s.exists){r.push({path:i.path,kind:"write",body:i.body_md});continue}if(s.contentHash===i.content_hash){r.push({path:i.path,kind:"skip"});continue}if(s.verifyRecsStrippedHash===i.content_hash){r.push({path:i.path,kind:"skip",note:"local differs from cloud only by verify-recs corrections (written by the CLI, not by you)"});continue}if(i.generated){r.push({path:i.path,kind:"overwrite",body:i.body_md,note:s.locallyEdited?"discarded local edits \u2014 this is a cloud-generated file (edit it in the dashboard)":void 0});continue}if(s.trackingPointer&&s.locallyEdited){r.push({path:i.path,kind:"overwrite",body:i.body_md,note:"replaced the tracking-pointer stub with the cloud draft (the stub was written by `content track`, not by you)"});continue}if(i.path==="context.md"&&s.scaffoldContext&&!he(i.body_md)){r.push({path:i.path,kind:"overwrite",body:i.body_md,note:"replaced the `seoagent init` scaffold with the owner-authored cloud context (the scaffold was written by `init`, not by you)"});continue}if(s.locallyEdited&&!o(i.path)){r.push({path:i.path,kind:"conflict",note:"local newer than cloud, keeping local \u2014 use --force to take cloud"});continue}r.push({path:i.path,kind:"overwrite",body:i.body_md})}for(let i of e.deleted){let s=t[i];if(!(!s||!s.exists)){if(s.locallyEdited&&!o(i)){r.push({path:i,kind:"delete-skipped",note:"server deleted this but it has local edits \u2014 keeping it (use --force to delete)"});continue}r.push({path:i,kind:"delete"})}}return r}function Ug(e,t,n,r){let o=new Map;for(let s of t.artifacts)o.set(s.path,s.generated);let i=[];for(let s of e)s.kind!=="skip"&&i.push({path:s.path,kind:s.kind,class:_a(s.path,o.get(s.path)??!1),...s.note?{note:s.note}:{}});return i.length===0?null:{pulled_at:r,cursor:n,changes:i}}async function za(e){let t=await Ro(e);return t.ok?t.artifact?{ok:!0,body:t.artifact.body_md}:{ok:!1,error:`No cloud artifact found at "${e.path.replace(/^\/+/,"").replace(/\\/g,"/")}"`}:t}async function Ro(e){let t=await Ja({apiBase:e.apiBase,authHeader:e.authHeader,since:null,fetchImpl:e.fetchImpl});if(!t.ok)return{ok:!1,error:t.error};let n=e.path.replace(/^\/+/,"").replace(/\\/g,"/");return{ok:!0,artifact:t.manifest.artifacts.find(r=>r.path===n)??null}}function Va(e,t){return Co(e,t.split("/").join(Mg))}function Bg(e,t,n){let r={};for(let o of t){let i=Va(e,o);if(!qa(i)){r[o]={exists:!1,locallyEdited:!1};continue}let s=n[o],a=Ng(i,"utf-8"),l=!s||s.hash!==ue(a),c=ya(a),d=Ba(a);r[o]={exists:!0,contentHash:Wa(a),locallyEdited:l,...o==="context.md"&&he(a)?{scaffoldContext:!0}:{},...c?{trackingPointer:c}:{},...d.stripped>0?{verifyRecsStrippedHash:Wa(d.text)}:{}}}return r}async function Ja(e){let t=e.fetchImpl??fetch,n=`${e.apiBase}/api/cli/sync`+(e.since?`?since=${encodeURIComponent(e.since)}`:"");try{let r=await t(n,{method:"GET",headers:{Authorization:e.authHeader,Accept:"application/json"}});if(!r.ok){let i=await r.text().catch(()=>"");return{ok:!1,error:`${r.status} ${i.slice(0,200)}`.trim()}}let o=await r.json().catch(()=>null);return!o||!Array.isArray(o.artifacts)||typeof o.now!="string"?{ok:!1,error:"Malformed manifest response"}:(Array.isArray(o.deleted)||(o.deleted=[]),{ok:!0,manifest:o})}catch(r){return{ok:!1,error:r.message}}}async function Xa(e){let t=Co(e.projectDir,b),n={ok:!0,written:0,overwritten:0,skipped:0,conflicts:0,conflictPaths:[],pointerOverwrites:{},deleted:0,warnings:[],cursor:e.since};if(!qa(t))return{...n,ok:!0};let r=await Ja({apiBase:e.apiBase,authHeader:e.authHeader,since:e.since,fetchImpl:e.fetchImpl});if(!r.ok)return{...n,ok:!1,error:r.error};let o=r.manifest,i=[...o.artifacts.map(d=>d.path),...o.deleted],s=Bg(t,i,e.stateFiles),a=Fg(o,s,{force:e.force,forcePaths:e.forcePaths}),l={...n,pointerOverwrites:{},cursor:o.now};for(let d of a){let f=Va(t,d.path);try{switch(d.kind){case"skip":l.skipped++;break;case"write":case"overwrite":{Lg(Dg(f),{recursive:!0});let p=d.body??"";Ga(f,p,"utf-8"),e.stateFiles[d.path]={hash:ue(p)},d.kind==="write"?l.written++:l.overwritten++;let g=s[d.path]?.trackingPointer;d.kind==="overwrite"&&g&&(l.pointerOverwrites[d.path]=g),d.note&&l.warnings.push(`${d.path}: ${d.note}`);break}case"conflict":l.conflicts++,l.conflictPaths.push(d.path),l.warnings.push(`${d.path}: ${d.note??"conflict"}`);break;case"delete":jg(f,{force:!0}),delete e.stateFiles[d.path],l.deleted++;break;case"delete-skipped":l.conflicts++,l.conflictPaths.push(d.path),l.warnings.push(`${d.path}: ${d.note??"delete skipped"}`);break}}catch(p){l.ok=!1,l.error=`${d.path}: ${p.message}`}}(l.conflicts>0||!l.ok)&&(l.cursor=e.since);let c=Ug(a,o,l.cursor,new Date().toISOString());if(c)try{Ga(Co(t,Tn),JSON.stringify(c,null,2)+`
824
- `,"utf-8")}catch{}return l}var un="context.md",qg="context.md: the cloud copy is owner-authored and your local version does not derive from it \u2014 NOT pushed, both copies kept. Compare with `seoagent pull --print context.md`, merge into the local file, then sync; or take the cloud copy with `seoagent sync --force context.md`.",Yg="context.md: replaced the local `seoagent init` scaffold with the owner-authored cloud context (the scaffold was written by `init`, not by you).",zg="context.md: took the cloud copy (`--force context.md`) \u2014 the local version was replaced.";function Vg(e){return he(e.localBody)?!0:!e.prevStateHash||e.prevStateHash!==ue(e.localBody)}function Jg(e){let{localBody:t,prevStateHash:n,cloudBody:r}=e;return r===null?{kind:"none"}:ue(t)===ue(r)?{kind:"none"}:he(r)?{kind:"none"}:he(t)?{kind:"restore",body:r,notice:Yg}:n&&n===ue(r)?{kind:"none"}:e.forceTakeCloud?{kind:"restore",body:r,notice:zg}:e.forcePushLocal?{kind:"none"}:{kind:"block-push",notice:qg}}var dn={restored:!1,blockPush:!1,notices:[]};async function Qa(e){let t=Kg(e.seoagentDir,un);if(!Hg(t))return dn;let n;try{n=Gg(t,"utf-8")}catch{return dn}let r=e.stateFiles[un]?.hash??null;if(!Vg({localBody:n,prevStateHash:r}))return dn;let o=await Ro({apiBase:e.apiBase,authHeader:e.authHeader,path:un,fetchImpl:e.fetchImpl});if(!o.ok)return{restored:!1,blockPush:!he(n)&&(!r||r!==ue(n)),notices:[]};let i=Jg({localBody:n,prevStateHash:r,cloudBody:o.artifact?.body_md??null,forceTakeCloud:e.forcePaths?.includes(un)===!0,forcePushLocal:e.force===!0});switch(i.kind){case"none":return dn;case"restore":try{Wg(t,i.body,"utf-8")}catch{return dn}return e.stateFiles[un]={hash:ue(i.body)},{restored:!0,blockPush:!1,notices:[i.notice]};case"block-push":return{restored:!1,blockPush:!0,notices:[i.notice]}}}import{existsSync as el,mkdirSync as tl,readFileSync as Xg,writeFileSync as Eo}from"fs";import{dirname as nl,join as Qg}from"path";var Ao=1,Za=500;function Po(e){return Qg(e,b,Ii)}function lr(e){let t=Po(e);if(!el(t))return[];try{let n=Xg(t,"utf-8"),r=JSON.parse(n);if(!r||typeof r!="object")return[];let o=r;return o.version!==Ao||!Array.isArray(o.entries)?[]:o.entries.filter(Zg)}catch{return[]}}function rl(e,t){let n=Po(e),o=lr(e).filter(a=>a.action_id!==t.action_id);o.push({action_id:t.action_id,status:t.status,reason:t.reason,queued_at:new Date().toISOString()});let i=o.length>Za?o.slice(-Za):o,s={version:Ao,entries:i};try{tl(nl(n),{recursive:!0}),Eo(n,JSON.stringify(s,null,2),"utf-8")}catch{}}function ol(e,t){if(t.length===0)return;let n=Po(e),r=lr(e).filter(i=>!t.includes(i.action_id)),o={version:Ao,entries:r};try{if(r.length===0&&el(n)){Eo(n,JSON.stringify(o,null,2),"utf-8");return}tl(nl(n),{recursive:!0}),Eo(n,JSON.stringify(o,null,2),"utf-8")}catch{}}function Zg(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.action_id=="number"&&(t.status==="completed"||t.status==="failed")&&(t.reason===null||typeof t.reason=="string")&&typeof t.queued_at=="string"}import{existsSync as il,readFileSync as em,unlinkSync as tm,writeFileSync as nm,openSync as rm,closeSync as om,mkdirSync as im}from"fs";import{dirname as sm,join as am}from"path";var lm=6e4;function sl(e){return am(e,b,Oi)}function al(e,t={}){let n=t.now??Date.now,r=t.pid??process.pid,o=t.staleMs??lm,i=sl(e);if(!il(i))return cr(i,r,n());let s=cl(i);return!s||n()-s.started_at>o||!cm(s.pid)?cr(i,r,n()):{acquired:!1,reason:"held-by-live-process",held_by_pid:s.pid}}function ll(e,t={}){let n=t.pid??process.pid,r=sl(e);if(!il(r))return;let o=cl(r);if(!(o&&o.pid!==n))try{tm(r)}catch{}}function cr(e,t,n){let r={pid:t,started_at:n};try{im(sm(e),{recursive:!0});let o=rm(e,"w");try{nm(o,JSON.stringify(r))}finally{om(o)}return{acquired:!0}}catch{return{acquired:!1,reason:"held-but-pid-unknown"}}}function cl(e){try{let t=em(e,"utf-8"),n=JSON.parse(t);return n&&typeof n=="object"&&typeof n.pid=="number"&&typeof n.started_at=="number"?n:null}catch{return null}}function cm(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}import{existsSync as bl,mkdirSync as wm,readFileSync as kl,writeFileSync as bm}from"fs";import{dirname as km,join as pn}from"path";import{existsSync as Io,readFileSync as fl,readdirSync as um}from"fs";import{join as ur}from"path";var pr="llms.md",dm=160,ul=100;function dr(e,t=dm){let n=e.replace(/\s+/g," ").replace(/[[\]]/g,"").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function Oo(e){let t=D(e);if(t==="/")return"Home";let r=(t.split("/").filter(Boolean).pop()||"Home").replace(/[-_]+/g," ").replace(/\.(html?|md|php)$/i,"").trim();return r?r.split(" ").map(o=>o.length>0?o[0].toUpperCase()+o.slice(1):o).join(" "):"Home"}var pm=new Set(["readme","changelog","license","licence","contributing","code_of_conduct","code-of-conduct","security","authors","notice"]);function gl(e){let t=D(e).split("/").filter(Boolean).pop();return t?pm.has(t.replace(/\.(md|mdx|txt|html?)$/i,"").toLowerCase()):!1}function dl(e){let t=dr(e.label,80)||Oo(e.url),n=e.description?dr(e.description):"";return`- [${t}](${e.url})${n?`: ${n}`:""}`}function ml(e){let t=[`# ${dr(e.siteName,100)}`,""];if(e.summary&&t.push(`> ${dr(e.summary,300)}`,""),e.pages.length>0){t.push("## Pages","");for(let n of e.pages)t.push(dl(n));t.push("")}if(e.articles.length>0){t.push("## Articles","");for(let n of e.articles)t.push(dl(n));t.push("")}return t.join(`
824
+ `,"utf-8")}catch{}return l}var un="context.md",qg="context.md: the cloud copy is owner-authored and your local version does not derive from it \u2014 NOT pushed, both copies kept. Compare with `seoagent pull --print context.md`, merge into the local file, then sync; or take the cloud copy with `seoagent sync --force context.md`.",Yg="context.md: replaced the local `seoagent init` scaffold with the owner-authored cloud context (the scaffold was written by `init`, not by you).",zg="context.md: took the cloud copy (`--force context.md`) \u2014 the local version was replaced.";function Vg(e){return he(e.localBody)?!0:!e.prevStateHash||e.prevStateHash!==ue(e.localBody)}function Jg(e){let{localBody:t,prevStateHash:n,cloudBody:r}=e;return r===null?{kind:"none"}:ue(t)===ue(r)?{kind:"none"}:he(r)?{kind:"none"}:he(t)?{kind:"restore",body:r,notice:Yg}:n&&n===ue(r)?{kind:"none"}:e.forceTakeCloud?{kind:"restore",body:r,notice:zg}:e.forcePushLocal?{kind:"none"}:{kind:"block-push",notice:qg}}var dn={restored:!1,blockPush:!1,notices:[]};async function Qa(e){let t=Kg(e.seoagentDir,un);if(!Hg(t))return dn;let n;try{n=Gg(t,"utf-8")}catch{return dn}let r=e.stateFiles[un]?.hash??null;if(!Vg({localBody:n,prevStateHash:r}))return dn;let o=await Ro({apiBase:e.apiBase,authHeader:e.authHeader,path:un,fetchImpl:e.fetchImpl});if(!o.ok)return{restored:!1,blockPush:!he(n)&&(!r||r!==ue(n)),notices:[]};let i=Jg({localBody:n,prevStateHash:r,cloudBody:o.artifact?.body_md??null,forceTakeCloud:e.forcePaths?.includes(un)===!0,forcePushLocal:e.force===!0});switch(i.kind){case"none":return dn;case"restore":try{Wg(t,i.body,"utf-8")}catch{return dn}return e.stateFiles[un]={hash:ue(i.body)},{restored:!0,blockPush:!1,notices:[i.notice]};case"block-push":return{restored:!1,blockPush:!0,notices:[i.notice]}}}import{existsSync as el,mkdirSync as tl,readFileSync as Xg,writeFileSync as Eo}from"fs";import{dirname as nl,join as Qg}from"path";var Ao=1,Za=500;function Po(e){return Qg(e,b,Ii)}function lr(e){let t=Po(e);if(!el(t))return[];try{let n=Xg(t,"utf-8"),r=JSON.parse(n);if(!r||typeof r!="object")return[];let o=r;return o.version!==Ao||!Array.isArray(o.entries)?[]:o.entries.filter(Zg)}catch{return[]}}function rl(e,t){let n=Po(e),o=lr(e).filter(a=>a.action_id!==t.action_id);o.push({action_id:t.action_id,status:t.status,reason:t.reason,queued_at:new Date().toISOString()});let i=o.length>Za?o.slice(-Za):o,s={version:Ao,entries:i};try{tl(nl(n),{recursive:!0}),Eo(n,JSON.stringify(s,null,2),"utf-8")}catch{}}function ol(e,t){if(t.length===0)return;let n=Po(e),r=lr(e).filter(i=>!t.includes(i.action_id)),o={version:Ao,entries:r};try{if(r.length===0&&el(n)){Eo(n,JSON.stringify(o,null,2),"utf-8");return}tl(nl(n),{recursive:!0}),Eo(n,JSON.stringify(o,null,2),"utf-8")}catch{}}function Zg(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.action_id=="number"&&(t.status==="completed"||t.status==="failed")&&(t.reason===null||typeof t.reason=="string")&&typeof t.queued_at=="string"}import{existsSync as il,readFileSync as em,unlinkSync as tm,writeFileSync as nm,openSync as rm,closeSync as om,mkdirSync as im}from"fs";import{dirname as sm,join as am}from"path";var lm=6e4;function sl(e){return am(e,b,Oi)}function al(e,t={}){let n=t.now??Date.now,r=t.pid??process.pid,o=t.staleMs??lm,i=sl(e);if(!il(i))return cr(i,r,n());let s=cl(i);return!s||n()-s.started_at>o||!cm(s.pid)?cr(i,r,n()):{acquired:!1,reason:"held-by-live-process",held_by_pid:s.pid}}function ll(e,t={}){let n=t.pid??process.pid,r=sl(e);if(!il(r))return;let o=cl(r);if(!(o&&o.pid!==n))try{tm(r)}catch{}}function cr(e,t,n){let r={pid:t,started_at:n};try{im(sm(e),{recursive:!0});let o=rm(e,"w");try{nm(o,JSON.stringify(r))}finally{om(o)}return{acquired:!0}}catch{return{acquired:!1,reason:"held-but-pid-unknown"}}}function cl(e){try{let t=em(e,"utf-8"),n=JSON.parse(t);return n&&typeof n=="object"&&typeof n.pid=="number"&&typeof n.started_at=="number"?n:null}catch{return null}}function cm(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}import{existsSync as bl,mkdirSync as wm,readFileSync as kl,writeFileSync as bm}from"fs";import{dirname as km,join as pn}from"path";import{existsSync as Io,readFileSync as fl,readdirSync as um}from"fs";import{join as ur}from"path";var pr="llms.md",dm=160,ul=100;function dr(e,t=dm){let n=e.replace(/\s+/g," ").replace(/[[\]]/g,"").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function Oo(e){let t=D(e);if(t==="/")return"Home";let r=(t.split("/").filter(Boolean).pop()||"Home").replace(/[-_]+/g," ").replace(/\.(html?|md|php)$/i,"").trim();return r?r.split(" ").map(o=>o.length>0?o[0].toUpperCase()+o.slice(1):o).join(" "):"Home"}var pm=new Set(["readme","changelog","license","licence","contributing","contributors","code_of_conduct","code-of-conduct","security","authors","notice","agents","claude","cursorrules","codeowners","copying","maintainers"]);function gl(e){let t=D(e).split("/").filter(Boolean).pop();return t?pm.has(t.replace(/\.(md|mdx|txt|html?)$/i,"").toLowerCase()):!1}function dl(e){let t=dr(e.label,80)||Oo(e.url),n=e.description?dr(e.description):"";return`- [${t}](${e.url})${n?`: ${n}`:""}`}function ml(e){let t=[`# ${dr(e.siteName,100)}`,""];if(e.summary&&t.push(`> ${dr(e.summary,300)}`,""),e.pages.length>0){t.push("## Pages","");for(let n of e.pages)t.push(dl(n));t.push("")}if(e.articles.length>0){t.push("## Articles","");for(let n of e.articles)t.push(dl(n));t.push("")}return t.join(`
825
825
  `).replace(/\n+$/,`
826
826
  `)}function fm(e){let t=new Map,n=null;for(let r of e.split(/\r?\n/)){let o=/^##\s+(https?:\/\/\S+)\s*$/.exec(r);if(o){n=D(o[1]),t.has(n)||t.set(n,{});continue}if(!n)continue;if(/^##\s/.test(r)){n=null;continue}let i=/^-\s+\*\*title:\*\*\s+(.*)$/.exec(r);if(i&&i[1]!=="_(none)_"){t.get(n).title=i[1].trim();continue}let s=/^-\s+\*\*meta description:\*\*\s+(.*)$/.exec(r);s&&s[1]!=="_(none)_"&&(t.get(n).description=s[1].trim())}return t}function gm(e){let t=ur(e,b,"audit","evidence.md");if(!Io(t))return new Map;try{return fm(fl(t,"utf-8"))}catch{return new Map}}function mm(e,t){let n=ur(e,b,"content");if(!Io(n))return[];let r=new Map,o;try{o=um(n)}catch{return[]}for(let i of o.sort()){if(!i.toLowerCase().endsWith(".md"))continue;let s;try{s=ae(fl(ur(n,i),"utf-8")).data}catch{continue}let a=typeof s.canonical=="string"?s.canonical.trim():"",l=typeof s.status=="string"?s.status.toLowerCase():"";if(!a||l==="draft"||gl(a))continue;let c=typeof s.title=="string"&&s.title.trim()?s.title.trim():Oo(a),d=t.get(D(a)),f={url:a,label:d?.title||c,...d?.description?{description:d.description}:{}},p=typeof s.slug=="string"?s.slug.trim():i.slice(0,-3),g=D(a).split("/").filter(Boolean).pop()??"",y=p===g,h=r.get(a);(!h||y&&!h.slugMatchesUrl)&&r.set(a,{link:f,slugMatchesUrl:y})}return Array.from(r.values(),i=>i.link)}function hm(e){try{return new URL(e).host.toLowerCase().replace(/^www\./,"")}catch{return""}}function ym(e,t){let n=ur(e,b,"pages.md");if(!Io(n))return[];let r=t.toLowerCase().replace(/^https?:\/\//,"").replace(/\/.*$/,""),o=new Map;for(let i of lo(n).keys()){if(!/^https?:\/\//i.test(i))continue;let s=D(i);if(ye(s)||gl(i))continue;let l=`${hm(i)}${s}`;if(!o.get(l)){o.set(l,i);continue}let d="";try{d=new URL(i).hostname.toLowerCase()}catch{d=""}d===r&&o.set(l,i)}return Array.from(o.values())}function pl(e){return[...e].sort((t,n)=>{let r=D(t.url),o=D(n.url);return r==="/"?o==="/"?0:-1:o==="/"?1:r.localeCompare(o)})}function hl(e,t){let n=t.domain.replace(/^https?:\/\//,"").replace(/\/+$/,""),r=(()=>{try{return mt(e)}catch{return null}})(),o=gm(e),i=mm(e,o),s=new Set(i.map(d=>D(d.url))),a=[];for(let d of ym(e,n)){let f=D(d);if(s.has(f))continue;let p=o.get(f);a.push({url:d,label:p?.title||Oo(d),...p?.description?{description:p.description}:{}})}if(a.length===0&&i.length===0)return null;let l=r?.business?.name?.trim()||o.get("/")?.title||n,c=r?.business?.description?.trim()||o.get("/")?.description||null;return{siteName:l,summary:c,pages:pl(a).slice(0,ul),articles:pl(i).slice(0,ul)}}var fr=".well-known/okf",yl="llms.txt",wl={publicDir:null,publicDirSource:null,llmsSourceWritten:!1,llmsPublished:null,okfPublished:0,okfPublishedDir:null,llmsRoute:null,llmsRouteDrift:!1,skipped:[]};function To(e,t){try{return bl(e)&&kl(e,"utf-8")===t?!1:(wm(km(e),{recursive:!0}),bm(e,t,"utf-8"),!0)}catch{return!1}}function Pt(e,t){if(!t.domain||t.domain==="unknown")return{...wl,skipped:["no-domain"]};let n=Un(e,t.public_dir??null),r={...wl,publicDir:n.dir,publicDirSource:n.source,skipped:[]},o=null;try{let s=hl(e,t);o=s?ml(s):null}catch{o=null}if(o===null)r.skipped.push("llms-no-content");else if(r.llmsSourceWritten=To(pn(e,b,pr),o),r.llmsRoute=Ui(e,n.dir),r.llmsRoute)r.skipped.push("llms-route-owned"),r.llmsRouteDrift=r.llmsSourceWritten&&t.llms_owner!=="route";else if(n.dir){let s=pn(e,n.dir,yl);To(s,o)&&(r.llmsPublished=`${n.dir}/${yl}`)}let i=bt(e);if(!bl(i))r.skipped.push("okf-missing");else if(Ks(i))r.skipped.push("okf-placeholder");else if(!Qn(i).ok)r.skipped.push("okf-invalid");else if(n.dir){let s=pn(e,n.dir,fr),a=0;for(let l of qs(i)){let c;try{c=kl(pn(i,l),"utf-8")}catch{continue}To(pn(s,l),c)&&a++}a>0&&(r.okfPublished=a,r.okfPublishedDir=`${n.dir}/${fr}`)}return n.dir||r.skipped.push("no-public-dir"),r}function vl(e,t){if(!e)return[];let n=[],r=[];return e.llmsPublished&&r.push(e.llmsPublished),e.okfPublishedDir&&r.push(`${e.okfPublishedDir}/ (${e.okfPublished} file${e.okfPublished===1?"":"s"})`),r.length>0&&n.push({text:`ai-files: published ${r.join(" and ")} \u2014 commit these so answer engines can read them.`,tone:"dim",always:!0}),e.skipped.includes("okf-placeholder")&&n.push({text:"ai-files: .seoagent/okf/ is still the scaffold. Fill it (see references/open-knowledge-format.md) and it publishes itself on the next sync.",tone:"dim",always:!1}),e.skipped.includes("okf-invalid")&&n.push({text:`ai-files: .seoagent/okf/ has validation errors, so it was NOT published. Run \`${t("okf validate")}\` and fix them.`,tone:"warn",always:!1}),e.llmsRouteDrift&&n.push({text:`ai-files: .seoagent/llms.md changed, but ${e.llmsRoute} already serves /llms.txt, so nothing was published \u2014 a file in your static dir would shadow that route. Compare the two, or set \`llms_owner: route\` in .seoagent/project.md to own the file yourself and stop this notice.`,tone:"dim",always:!1}),e.skipped.includes("no-public-dir")&&n.push({text:"ai-files: couldn't tell which directory this project serves as static files. Set `public_dir:` in .seoagent/project.md (`public`, `static`, or a nested path like `apps/web/public` in a monorepo) so llms.txt and the OKF bundle actually get served.",tone:"dim",always:!1}),n}function Cm(e){try{let t=At(e);return t.evidenceFound?t:void 0}catch{return}}var Rm=new Set([".md"]),Em=new Set(["inbox"]);function Am(e){let t=[];function n(r,o){if(Lo(r))for(let i of $m(r,{withFileTypes:!0})){if(i.name.startsWith(".")||o===""&&Em.has(i.name))continue;let s=No(r,i.name);if(i.isDirectory())n(s,o?`${o}/${i.name}`:i.name);else if(i.isFile()){let a=i.name.lastIndexOf("."),l=a===-1?"":i.name.slice(a);Rm.has(l)&&t.push(s)}}}return n(e,""),t}function xl(e){let t=e.replace(/[^a-zA-Z0-9._-]/g,"_");return No(jr,`${t}.json`)}var Pm=14400*1e3;function Im(e){let t=xl(e);if(!Lo(t))return{files:{},last_synced_at:null};try{return JSON.parse($l(t,"utf-8"))}catch{return{files:{},last_synced_at:null}}}function Om(e,t){vm(jr,{recursive:!0}),xm(xl(e),JSON.stringify(t,null,2)+`
827
827
  `,"utf-8")}function Tm(e,t){return Sm(e,t).split(_m).join("/")}async function Lm(e,t){try{let n=await O(`${e}/api/cli/actions/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:t},body:JSON.stringify({})});if(!n.ok){let o=await n.text().catch(()=>"");return{ok:!1,actions:[],error:`${n.status} ${o.slice(0,200)}`}}let r=await n.json().catch(()=>null);return!r||r.status!=="ok"||!Array.isArray(r.actions)?{ok:!1,actions:[],error:"Malformed response"}:{ok:!0,actions:r.actions}}catch(n){return{ok:!1,actions:[],error:n.message}}}async function Nm(e,t,n){try{let r=await O(`${e}/api/cli/sync`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:n},body:JSON.stringify(t)});if(!r.ok){let i=await r.text().catch(()=>"");return{ok:!1,status:r.status,error:i.slice(0,200)}}let o=typeof r.json=="function"?await r.json().catch(()=>null):null;return{ok:!0,status:r.status,...o?.agent_notice?{agentNotice:o.agent_notice}:{}}}catch(r){return{ok:!1,status:0,error:r.message}}}async function Sl(e,t={}){let n=Cm(e),r=c=>{let d=n?{...c,verifyRecs:n}:{...c};return i?{...d,aiFiles:i}:d},o=_(e),i=null;if(o)try{i=Pt(e,o)}catch{}let s=j(o?.domain);if(!s)return r({ok:!0,reason:"no-auth",synced:0,failed:0,errors:[]});if(!o)return r({ok:!0,reason:"no-project",synced:0,failed:0,errors:[]});if(o.domain===Ne)return r({ok:!0,reason:"domain-unknown",synced:0,failed:0,errors:[]});let a=No(e,b);if(!Lo(a))return r({ok:!0,reason:"no-project",synced:0,failed:0,errors:[]});if(!al(e).acquired)return r({ok:!0,reason:"busy",synced:0,failed:0,errors:[]});try{return r(await jm(e,t,s,o,a))}finally{ll(e)}}async function jm(e,t,n,r,o){let i=n.api_base||N.BASE,s=`Bearer ${n.user_token}:${n.website_token}`,a=await De({apiBase:i,authHeader:s,localDomain:r.domain});if(a.verdict==="mismatch")return{ok:!0,reason:"project-mismatch",synced:0,failed:0,errors:[],cloudDomain:a.cloudDomain,localDomain:r.domain};if(a.verdict==="unverified")return{ok:!0,reason:"unverified",synced:0,failed:0,errors:[`could not verify cloud project binding: ${a.detail}`]};let l=Im(r.domain);try{ba(e,r)}catch{}let c=Am(o),d=0,f=0,p=[],g=[],y=0,h=await Dm(e,i,s),w={restored:!1,blockPush:!1,notices:[]};if((!t.pathFilter||"context.md".endsWith(t.pathFilter))&&(w=await Qa({seoagentDir:o,apiBase:i,authHeader:s,stateFiles:l.files,force:t.force,forcePaths:t.forcePaths}),p.push(...w.notices)),!t.pullOnly)for(let q of c){let z=Tm(o,q);if(t.pathFilter&&!z.endsWith(t.pathFilter)||z==="context.md"&&w.blockPush)continue;let Ke=$l(q,"utf-8"),at=ue(Ke),Pn=l.files[z];if(!(!Pn||Pn.hash!==at)&&!t.force)continue;y++;let qe=await Nm(i,{path:z,contents:Ke,domain:r.domain},s);qe.ok?(l.files[z]={hash:at},d++,qe.agentNotice&&p.push(`${z}: ${qe.agentNotice}`)):(f++,g.push(`${z}: ${qe.status} ${qe.error??""}`.trim()))}let $=await Lm(i,s),A=0,F=0,C=[],R=0,G=0;!$.ok&&$.error&&g.push(`pull actions: ${$.error}`);let K,ee=[],Nt=new Map,jt=!1,An=l.last_synced_at;if(!t.pushOnly){let q=await Xa({projectDir:e,apiBase:i,authHeader:s,since:l.last_synced_at,stateFiles:l.files,force:t.force,forcePaths:t.forcePaths});q.ok?An=q.cursor:(jt=!0,q.error&&g.push(`pull: ${q.error}`)),K={written:q.written,overwritten:q.overwritten,skipped:q.skipped,conflicts:q.conflicts,deleted:q.deleted,warnings:q.warnings},ee=q.conflictPaths;for(let[z,Ke]of Object.entries(q.pointerOverwrites)){let at=z.match(/^content\/(.+)\.md$/)?.[1];at&&Nt.set(at,Ke)}}if($.ok){let q=xo(e);for(let[Se,lt]of Nt)q.set(Se,lt);let z=Sa(e,$.actions,{conflictedPaths:new Set(ee),localPointers:q});A=z.wrote,F=z.removed,R=z.skippedUnknown;let Ke=l.announced_at?Date.parse(l.announced_at):NaN,Pn=z.pendingIds.length>0&&(Number.isNaN(Ke)||Date.now()-Ke>=Pm)?new Set:new Set(l.announced_action_ids??[]),In=new Set(z.pendingIds.filter(Se=>!Pn.has(Se)));C=z.pending.filter(Se=>In.has(Se.id)),G=In.size-C.length,l.announced_action_ids=z.pendingIds,In.size>0&&(l.announced_at=new Date().toISOString());let qe=va($.actions);K&&ee.length>0&&(K.warnings=K.warnings.map(Se=>{let lt=ee.find(Nr=>Se.startsWith(`${Nr}:`)),Lr=lt?qe.get(lt):void 0;return!lt||!Lr?.length?Se:`${Se} \u2014 blocks inbox action${Lr.length===1?"":"s"} ${Lr.map(Nr=>`#${Nr}`).join(", ")}; take the cloud copy with \`seoagent sync --force ${lt}\``}))}let We=!!K&&K.written+K.overwritten+K.deleted+K.conflicts>0;if(l.last_synced_at=An,Om(r.domain,l),y===0&&A===0&&F===0&&!We&&!w.restored&&w.notices.length===0&&h.flushed===0&&h.dropped===0&&!jt&&f===0)return{ok:!0,reason:"no-changes",synced:0,failed:0,errors:g,actionsPulled:0,actionsRemoved:0,actionsNew:[],actionsUnknown:R,actionsUnknownNew:G,acksFlushed:0,acksDropped:0,pull:K};let Ei=f===0&&!jt;return{ok:Ei,reason:Ei?void 0:"error",synced:d,failed:f,errors:g,...p.length>0?{notices:p}:{},actionsPulled:A,actionsRemoved:F,actionsNew:C,actionsUnknown:R,actionsUnknownNew:G,acksFlushed:h.flushed,acksDropped:h.dropped,pull:K}}async function Dm(e,t,n){let r=lr(e);if(r.length===0)return{flushed:0,dropped:0};let o=0,i=0,s=[];for(let a of r){let l=await Mm(a,t,n);l==="flushed"?(o++,s.push(a.action_id)):l==="already-settled"&&(i++,s.push(a.action_id))}return s.length>0&&ol(e,s),{flushed:o,dropped:i}}async function Mm(e,t,n){try{let r=await O(`${t}/api/cli/actions/${e.action_id}/ack`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:n},body:JSON.stringify({status:e.status,error_message:e.status==="failed"?e.reason:null,result:e.status==="failed"?{declined:!0,reason:e.reason}:{applied:!0}})});return r.ok?"flushed":r.status===409||r.status>=400&&r.status<500?"already-settled":"transient"}catch{return"transient"}}function _l(e,t=3e4){let n=setTimeout(e,t);return n.unref?.(),{cancel:()=>clearTimeout(n)}}function Cl(e){let t;try{t=_(e)}catch{return{refreshed:!1,reason:"error"}}if(!t)return{refreshed:!1,reason:"no-project"};let n=t.skill_version||t.seoagent_version||"0.0.0";if(He(I,n)<=0){if(!t.skill_version)try{V(e,{skill_version:n})}catch{}return{refreshed:!1,reason:"up-to-date"}}try{return gt(e),V(e,{skill_version:I}),{refreshed:!0,from:n,to:I,reason:"refreshed"}}catch{return{refreshed:!1,reason:"error"}}}function jo(e){let t;try{t=_(e)}catch{return{refreshed:!1,from:null,to:I,reason:"error"}}if(!t)return{refreshed:!1,from:null,to:I,reason:"no-project"};let n=t.skill_version||t.seoagent_version||null;try{return gt(e),V(e,{skill_version:I}),{refreshed:!0,from:n,to:I,reason:"refreshed"}}catch{return{refreshed:!1,from:n,to:I,reason:"error"}}}import{createHash as Fm}from"crypto";import{existsSync as BS,mkdirSync as Um,readFileSync as Bm,writeFileSync as Hm}from"fs";import{join as Gm}from"path";var Wm="/cli-skill/manifest.json",Km=360*60*1e3,qm=4e3,Ym=64,zm=4*1024*1024,Rl=Gm(W,"skill-check.json"),Vm=e=>Fm("sha256").update(e).digest("hex");function Jm(e){if(typeof e!="object"||e===null)return null;let t=e;if(typeof t.hash!="string"||!/^[0-9a-f]{64}$/.test(t.hash)||typeof t.min_cli!="string"||!/^\d+\.\d+\.\d+/.test(t.min_cli)||!Array.isArray(t.files)||t.files.length===0||t.files.length>Ym)return null;let n=[],r=0;for(let o of t.files){if(typeof o!="object"||o===null)return null;let i=o;if(typeof i.path!="string"||typeof i.sha256!="string"||!/^[A-Za-z0-9._/-]+$/.test(i.path)||i.path.startsWith("/")||i.path.split("/").includes("..")||!i.path.endsWith(".md")||!/^[0-9a-f]{64}$/.test(i.sha256))return null;let s=typeof i.bytes=="number"?i.bytes:0;r+=s,n.push({path:i.path,sha256:i.sha256,bytes:s})}return r>zm||!n.some(o=>o.path==="SKILL.md")?null:{hash:t.hash,min_cli:t.min_cli,files:n}}function Xm(e,t,n=Km){if(!e)return!0;let r=Date.parse(e);return Number.isNaN(r)?!0:t.getTime()-r>=n}function Qm(){try{return JSON.parse(Bm(Rl,"utf-8"))}catch{return{}}}function Zm(e){try{Um(W,{recursive:!0}),Hm(Rl,JSON.stringify({checkedAt:e}),"utf-8")}catch{}}async function eh(e){try{let t=await fetch(e,{signal:AbortSignal.timeout(qm),headers:{"User-Agent":`seoagent-cli/${I}`}});return t.ok?await t.text():null}catch{return null}}async function El(e,t={}){try{let n=_(e);if(!n)return{updated:!1,reason:"no-project"};let r=t.now??new Date,o=Qm();if(!t.force&&!Xm(o.checkedAt,r))return{updated:!1,reason:"throttled"};let i=(t.baseUrl??N.BASE).replace(/\/$/,""),s=t.fetchText??eh,a=await s(`${i}${Wm}`);if(Zm(r.toISOString()),a===null)return{updated:!1,reason:"unreachable"};let l;try{l=Jm(JSON.parse(a))}catch{l=null}if(!l)return{updated:!1,reason:"malformed"};if(n.skill_hash===l.hash)return{updated:!1,reason:"up-to-date"};if(He(I,l.min_cli)<0)return{updated:!1,reason:"cli-too-old",minCli:l.min_cli};let c={};for(let d of l.files){let f=await s(`${i}/cli-skill/${d.path}`);if(f===null)return{updated:!1,reason:"unreachable"};if(Vm(f)!==d.sha256)return{updated:!1,reason:"verify-failed"};c[d.path]=f}return rs(e,c),V(e,{skill_hash:l.hash}),{updated:!0,reason:"updated",fileCount:l.files.length}}catch{return{updated:!1,reason:"error"}}}import{existsSync as th,mkdirSync as nh,readFileSync as rh,writeFileSync as oh}from"fs";var ih="https://registry.npmjs.org/@seoagent-official/seoagent/latest",sh=1440*60*1e3,ah=720*60*1e3,lh=2e3;function ch(e,t,n=sh){if(!e.checkedAt)return!0;let r=Date.parse(e.checkedAt);return Number.isNaN(r)?!0:t.getTime()-r>=n}function uh(e){let{current:t,latest:n,cache:r,now:o}=e,i=e.notifyIntervalMs??ah;if(!n||He(n,t)<=0)return null;if(r.notifiedVersion===n&&r.notifiedAt){let s=Date.parse(r.notifiedAt);if(!Number.isNaN(s)&&o.getTime()-s<i)return null}return`\u2191 SEOAgent ${n} is available (you have ${t}). Ask me to run \`seoagent update-cli\`, or run it yourself, to upgrade the CLI + all your projects.`}async function dh(e){let t=e.readCache();if(ch(t,e.now,e.checkIntervalMs)){let r=await e.fetchLatest();t={...t,checkedAt:e.now.toISOString(),...r?{latest:r}:{}},e.writeCache(t)}let n=uh({current:e.current,latest:t.latest,cache:t,now:e.now,notifyIntervalMs:e.notifyIntervalMs});return n&&t.latest&&e.writeCache({...t,notifiedVersion:t.latest,notifiedAt:e.now.toISOString()}),n}function ph(){try{return th(Ln)?JSON.parse(rh(Ln,"utf-8")):{}}catch{return{}}}function fh(e){try{nh(W,{recursive:!0}),oh(Ln,JSON.stringify(e,null,2)+`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seoagent-official/seoagent",
3
- "version": "1.92.0",
3
+ "version": "1.93.0",
4
4
  "description": "The persistent AI SEO agent for Claude Code. Audits, keyword strategy, briefs, articles, real product screenshots from your repo, and the autopilot loop (cloud detects → CLI executes → ack closes) — other SEO tools write the prompt, SEOAgent runs it.",
5
5
  "type": "module",
6
6
  "bin": {