document360-writer 0.5.184 → 0.5.185
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -375,10 +375,10 @@ ${n.map(h=>` \u25CB ${h.title}`).join(`
|
|
|
375
375
|
`):null}function Yu(e,t){let n=t.trim().toLowerCase();if(!n)return null;let o=Gr(e).find(r=>r.status==="open"&&r.title.trim().toLowerCase()===n);return o?[`Execute this open docs-roadmap step: "${o.title}".`,o.run?`Its run command: ${o.run}`:"",o.body?`Step detail:
|
|
376
376
|
${o.body}`:"","",`Close the loop IN THE SAME TURN the step's goal state is reached: call d360_roadmap_done with exactly the title "${o.title}", then tell the user it is marked done. This INCLUDES discovering the goal already holds \u2014 "no action needed" completes the STEP, not just the turn, so stamp it done then too. Leave it open ONLY if the work is genuinely incomplete (blocked, or background results not yet applied) \u2014 then say exactly what remains before it can be closed.`].filter(Boolean).join(`
|
|
377
377
|
`):null}async function zu(e,t){let n=t.cwd;if(e[0]?.toLowerCase()==="done"){let r=Yr(n,e.slice(1).join(" ").trim());return console.log(r.ok?M(r.line):B(r.line)),{kind:"continue"}}let o=Sa(n);console.log(W(o[0]??""));for(let r of o.slice(1))console.log(r.startsWith("(")?y(r):r);return{kind:"continue"}}var Ku={help:_s,"?":_s,clear:Gc,exit:Ms,quit:Ms,init:Hs,mcp:dr,publish:kd,audit:ro,discover:bd,scope:vd,pull:Nd,resolve:Ad,convert:Id,write:Fd,draft:Vd,document:Gd,resume:Kd,rename:Xd,profile:Jd,model:tu,doctor:ao,workspace:au,project:cu,"allow-prod":lu,login:du,logout:uu,screenshot:async(e,t)=>{let n=Zn(e);return n.mode==="capture"?ca(n.rest,t):n.mode==="verify"?pu(n.rest,t):n.mode==="checklist"?Sn():Rr(e,t)},capture:ca,"capture-setup":Sn,devhints:ol,inbox:Pu,"catch-up":Tu,update:Au,reset:Ou,check:Lu,review:Fu,reorder:Wu,structure:Uu,genre:Vr,roadmap:zu};function Xu(e){let t=e.trim();if(!t.startsWith("/"))return null;let n=t.slice(1).split(/\s+/),o=(n[0]??"").toLowerCase();return o?{name:o,args:n.slice(1)}:null}wt();var jw="Or just tell me what to write or update.",Nw='\u{1F4ED} No docs yet for this repo. Tell me "write the docs for this repo" and I\u2019ll read the code and draft a structure \u2014 or /audit to see what the docs should cover.';function ve(e){return e===1?"":"s"}function zr(e){return e.kind==="cmd"?`\u21E5 tab to run ${e.cmd} \xB7 or just ask me anything\u2026`:null}function yo(e){return e.kind==="cmd"?`I\u2019d start with ${e.cmd} \u2014 ${e.reason}.`:`Just tell me: \u201C${e.text}\u201D.`}var Iw={title:"What kind of product is this repo? (sets the doc-craft playbook \u2014 otherwise the docs stay generic)",options:[{cmd:"/genre web",desc:"web app / SaaS UI"},{cmd:"/genre cli",desc:"command-line tool"},{cmd:"/genre service",desc:"API / backend service"},{cmd:"/genre library",desc:"SDK / library"}]};function Ow(e){let t=[];if(e.devhints!=="current"&&e.builderStarted){let n=e.devhintsToVersion?`v${e.devhintsToVersion}`:"a newer version",o=e.devhints==="stale"&&e.devhintsCompletedVersion?` (your builder is on v${e.devhintsCompletedVersion})`:"";t.push({key:"devhints",bullet:`dev\u2194docs protocol moved to ${n}${o} \u2014 your docs aren\u2019t blocked`,lead:{kind:"cmd",cmd:"/devhints",reason:`one paste updates your builder to ${n}`},picker:null,follow:"Also run /devhints when you get a second \u2014 your builder\u2019s protocol is behind.",tone:"warn"})}if(e.genreUnknown&&t.push({key:"genre",bullet:"the doc genre isn\u2019t set \u2014 I can\u2019t load the right doc-craft playbook yet",lead:null,picker:Iw,follow:"Then pick the doc genre below (it sets the playbook I write with)."}),e.discovery&&e.discovery.status!=="confident"){let n=e.discovery.openQuestions;t.push(e.discovery.status==="pending"?{key:"discovery",bullet:"your existing docs aren\u2019t grounded in a product brief yet",lead:{kind:"cmd",cmd:"/discover",reason:"it interviews your builder and grounds the docs before you rewrite or publish them"},picker:null,follow:"Then /discover grounds your docs in a product brief (do this before the rewrite/publish steps)."}:n>0?{key:"discovery",bullet:`product discovery is waiting on ${n} answer${ve(n)} from your builder \u2014 nudge them`,lead:null,picker:null,follow:"Discovery is waiting on your builder\u2019s answers \u2014 nudge them, then /catch-up folds the answers in once they reply."}:{key:"discovery",bullet:"product discovery is ready to continue",lead:{kind:"cmd",cmd:"/discover",reason:"it continues interviewing your builder to ground the docs"},picker:null,follow:"Then /discover continues building the product brief."})}if(e.directives>0||e.pendingText){let n=e.directives>0&&e.pendingText?"it actions your directives and clears the builder\u2019s queue":e.directives>0?"it actions the directives you left":"it clears everything your builder queued",o=[];e.directives>0&&o.push(`${e.directives} owner directive${ve(e.directives)} waiting`),e.pendingText&&o.push(`your builder left ${e.pendingText}`),t.push({key:"catchup",bullet:o.join(`
|
|
378
|
-
\u2022 `),lead:{kind:"cmd",cmd:"/catch-up",reason:n},picker:null,follow:"Then /catch-up clears what\u2019s queued for the docs."})}if(e.hasDocs&&e.pendingWrites>0){let n=e.pendingWrites;t.push({key:"write",bullet:`${n} planned article${ve(n)} still unwritten`,lead:{kind:"cmd",cmd:"/write",reason:"it finishes the articles already planned"},picker:null,follow:`Then /write finishes the ${n} planned article${ve(n)}.`})}if(e.localAhead>0){let n=e.localAhead;t.push({key:"publish",bullet:`${n} article${ve(n)} changed locally \u2014 ready to publish`,lead:{kind:"cmd",cmd:"/publish",reason:`it pushes your ${n} local edit${ve(n)} up to Document360`},picker:null,follow:`Then /publish pushes your ${n} local edit${ve(n)} up.`})}if(e.conflicts>0){let n=e.conflicts;t.push({key:"resolve",bullet:`${n} article${ve(n)} changed both here and on Document360 (conflicts) \u2014 /publish skips these`,lead:{kind:"cmd",cmd:"/resolve",reason:"it walks each conflict \u2014 keep yours, take the portal's, or skip"},picker:null,follow:`Then /resolve settles the ${n} conflict${ve(n)} (keep yours / take the portal's / skip).`})}if(e.hasDocs&&e.roadmap?.next){let n=e.roadmap,o=n.next;t.push({key:"roadmap",bullet:`docs campaign: ${n.done} of ${n.total} step${ve(n.total)} done \u2014 next: ${o.title}`,lead:o.run?{kind:"cmd",cmd:o.run,reason:"it\u2019s the next step of your docs campaign"}:{kind:"prompt",text:o.title,reason:"it\u2019s the next step of your docs campaign"},picker:null,follow:`Then the campaign continues: ${o.title} (/roadmap shows all ${n.total} steps).`})}if(e.
|
|
378
|
+
\u2022 `),lead:{kind:"cmd",cmd:"/catch-up",reason:n},picker:null,follow:"Then /catch-up clears what\u2019s queued for the docs."})}if(e.behind>0){let n=e.behind;t.push({key:"audit",bullet:`${n} code change${ve(n)} since your last docs check`,lead:{kind:"cmd",cmd:"/audit",reason:"it shows what the latest code changes touch (or /audit --auto on to run it for you)"},picker:null,follow:`After that, /audit covers the ${n} newer commit${ve(n)}.`})}if(e.hasDocs&&e.pendingWrites>0){let n=e.pendingWrites;t.push({key:"write",bullet:`${n} planned article${ve(n)} still unwritten`,lead:{kind:"cmd",cmd:"/write",reason:"it finishes the articles already planned"},picker:null,follow:`Then /write finishes the ${n} planned article${ve(n)}.`})}if(e.localAhead>0){let n=e.localAhead;t.push({key:"publish",bullet:`${n} article${ve(n)} changed locally \u2014 ready to publish`,lead:{kind:"cmd",cmd:"/publish",reason:`it pushes your ${n} local edit${ve(n)} up to Document360`},picker:null,follow:`Then /publish pushes your ${n} local edit${ve(n)} up.`})}if(e.conflicts>0){let n=e.conflicts;t.push({key:"resolve",bullet:`${n} article${ve(n)} changed both here and on Document360 (conflicts) \u2014 /publish skips these`,lead:{kind:"cmd",cmd:"/resolve",reason:"it walks each conflict \u2014 keep yours, take the portal's, or skip"},picker:null,follow:`Then /resolve settles the ${n} conflict${ve(n)} (keep yours / take the portal's / skip).`})}if(e.hasDocs&&e.roadmap?.next){let n=e.roadmap,o=n.next;t.push({key:"roadmap",bullet:`docs campaign: ${n.done} of ${n.total} step${ve(n.total)} done \u2014 next: ${o.title}`,lead:o.run?{kind:"cmd",cmd:o.run,reason:"it\u2019s the next step of your docs campaign"}:{kind:"prompt",text:o.title,reason:"it\u2019s the next step of your docs campaign"},picker:null,follow:`Then the campaign continues: ${o.title} (/roadmap shows all ${n.total} steps).`})}if(e.uncommittedDocs>0){let n=e.uncommittedDocs;t.push({key:"commit",bullet:`\u26A0 ${n} uncommitted change${ve(n)} under .d360-writer/ \u2014 tell your coding agent: "commit d360-writer's work"`,lead:null,picker:null,follow:null})}return t}function Qu(e){return e.find(t=>t.lead||t.picker)??null}function Ta(e,t){let n=Qu(t),o=[];n?.lead?o.push(yo(n.lead)):n?.picker&&o.push("Pick the genre below \u2014 one keypress, and it shapes everything I write.");for(let c of t.filter(p=>p!==n).slice(0,2))c.follow&&o.push(c.follow);let r=o.join(" "),s=t.filter(c=>c.bullet).map(c=>{let p=c.lead?.kind==="cmd"?c.lead.cmd:null;return` \u2022 ${c.bullet}${p&&!r.includes(p)?` \u2014 ${p}`:""}`}),i=[[e,...s].join(`
|
|
379
379
|
`)];return o.length&&i.push(o.join(" ")),i.push(jw),i.join(`
|
|
380
380
|
|
|
381
|
-
`)}function wo(e){if(!e.ready)return{kind:"idle"};let t=Ow(e);if(!e.hasDocs){let s=Qu(t);return s&&(s.lead?.kind==="cmd"||s.picker)?{kind:"recommend",rec:{note:Ta("\u{1F4ED} No docs yet for this repo \u2014 here\u2019s where things stand:",t),tone:s.tone??"info",lead:s.lead,picker:s.picker}}:{kind:"recommend",rec:{note:Nw,tone:"info",lead:{kind:"prompt",text:"write the docs for this repo",reason:"I\u2019ll read the code and draft a structure"},picker:null}}}if(t.length===0){let s=e.roadmap&&!e.roadmap.next?` Docs campaign complete \u2014 all ${e.roadmap.total} step${ve(e.roadmap.total)} done (/roadmap).`:"";return{kind:"recommend",rec:{note:`Welcome back. Your ${e.tracked} tracked article${ve(e.tracked)} for \u201C${e.profileName}\u201D are all in sync \u2014 /audit re-checks the code, /pull brings down portal edits.${s}`,tone:"info",lead:null,picker:null}}}let n=t.filter(s=>s.lead||s.picker),o=n[0]??null;return o?(o.key==="audit"||
|
|
381
|
+
`)}function wo(e){if(!e.ready)return{kind:"idle"};let t=Ow(e);if(!e.hasDocs){let s=Qu(t);return s&&(s.lead?.kind==="cmd"||s.picker)?{kind:"recommend",rec:{note:Ta("\u{1F4ED} No docs yet for this repo \u2014 here\u2019s where things stand:",t),tone:s.tone??"info",lead:s.lead,picker:s.picker}}:{kind:"recommend",rec:{note:Nw,tone:"info",lead:{kind:"prompt",text:"write the docs for this repo",reason:"I\u2019ll read the code and draft a structure"},picker:null}}}if(t.length===0){let s=e.roadmap&&!e.roadmap.next?` Docs campaign complete \u2014 all ${e.roadmap.total} step${ve(e.roadmap.total)} done (/roadmap).`:"";return{kind:"recommend",rec:{note:`Welcome back. Your ${e.tracked} tracked article${ve(e.tracked)} for \u201C${e.profileName}\u201D are all in sync \u2014 /audit re-checks the code, /pull brings down portal edits.${s}`,tone:"info",lead:null,picker:null}}}let n=t.filter(s=>s.lead||s.picker),o=n[0]??null;return o?(o.key==="audit"||n[1]?.key==="audit")&&e.behind>0&&e.autoAudit&&e.allowAutoAudit?{kind:"autoAudit",note:`\u{1F4CB} ${e.behind} code change${ve(e.behind)} since your last docs check \u2014 running /audit automatically (auto-audit is on)\u2026`}:{kind:"recommend",rec:{note:Ta("Welcome back \u2014 where your docs stand:",t),tone:o.tone??"info",lead:o.lead,picker:o.picker}}:{kind:"recommend",rec:{note:Ta("Welcome back \u2014 where your docs stand:",t),tone:"info",lead:null,picker:null}}}import{existsSync as Ea,readdirSync as Da}from"node:fs";import{spawnSync as Lw}from"node:child_process";import{join as Kr}from"node:path";import{readProjectConfig as Zu,resolveActiveProfile as ep,loadTokens as _w,isExpired as Mw,loadProfileMap as tp,localAheadPaths as Uw,loadKnownConflicts as Fw,readDocsPlan as Ww,devHintsGuidePath as Bw,DEFAULT_DOCS_DIR as Aa,roadmapProgress as Hw,listRoadmap as qw,readProductBriefState as Vw,reconcileCommitRequest as Gw}from"document360-engine";wt();function Ju(e){try{return Da(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&!t.name.startsWith(".")).length>6}catch{return!1}}function ja(e,t){let n=t??[];return n.length===0?["src","api","services","packages","modules"].some(o=>Ju(Kr(e,o))):n.some(o=>!o.includes("/")&&!o.endsWith(".md")&&Ju(Kr(e,o)))}function Na(e,t){try{let n=Zu(e);if(!n)return!1;let o=ep(e,t),r=tp(e,o.name);if(r&&Object.keys(r.articles).length>0)return!0;let s=Kr(e,(n.docsDir??Aa).replace(/\/+$/,""));return!!(Ea(s)&&Da(s).length>0||Ea(Bw(e)))}catch{return!1}}function ko(e,t,n){try{let o=Zu(e);if(!o)return null;let r=ep(e,t),s=_w(r.name),i=!!s&&(!Mw(s)||!!s.refreshToken),c=Na(e,t)||!ja(e,o.authoritativeSourceFiles),p=tp(e,r.name),h=p?Object.keys(p.articles).length:0,b=Kr(e,(o.docsDir??Aa).replace(/\/+$/,"")),$=!1;try{$=Ea(b)&&Da(b).length>0}catch{}let v=0;if(p?.lastAnalyzedCommit)try{let ae=Lw("git",["rev-list","--count",`${p.lastAnalyzedCommit}..HEAD`],{cwd:e,encoding:"utf8",timeout:1200});ae.status===0&&(v=parseInt((ae.stdout||"").trim(),10)||0)}catch{}let E=0;try{let ae=Ww(e);if(ae.length>0){let Ze=(o.docsDir??Aa).replace(/\/+$/,"");E=Ii(e,Ze,ae.map(Ue=>Ue.path)).length}}catch{}let R=fo(e),x=mo({...R,directives:0}),T=Uw(e,t),F=new Set(Fw(e,r.name)),G=T.filter(ae=>F.has(ae)).length,q=T.length-G,Y=qe(e),pe=Hw(e),J=Gw(e,new Date().toISOString()),re=Vw(e),le=re?{status:re.status,openQuestions:re.openQuestions}:null;return!le&&$&&qw(e).some(Ze=>Ze.status==="open"&&(Ze.run??"").trim()==="/discover")&&(le={status:"pending",openQuestions:0}),{ready:i&&c&&!n.claudeMissing,hasDocs:$,tracked:h,pendingText:x,directives:R.directives,behind:v,pendingWrites:E,localAhead:q,conflicts:G,autoAudit:!!o.autoAudit,profileName:r.name,allowAutoAudit:n.allowAutoAudit,devhints:Y.status,devhintsCompletedVersion:Y.completedVersion,devhintsToVersion:me,builderStarted:it(e),genreUnknown:n.genreUnknown,roadmap:pe,discovery:le,uncommittedDocs:J.dirty.length}}catch{return null}}K();var Yw={Bash:"command",PowerShell:"command",Read:"file_path",Write:"file_path",Edit:"file_path",NotebookEdit:"notebook_path",Glob:"pattern",Grep:"pattern",WebFetch:"url",WebSearch:"query",Agent:"description",Task:"description",Skill:"skill"},op=160,Oa=200,rp=40;function Le(e,t){let n=e.replace(/\s+/g," ").trim();return n.length<=t?n:n.slice(0,t-1)+"\u2026"}function np(e){let t=Object.entries(e).filter(([,o])=>o!=null&&o!=="");if(t.length===0)return null;let n=t.slice(0,4).map(([o,r])=>`${o}: ${Le(typeof r=="string"?r:JSON.stringify(r),rp)}`);return t.length>4&&n.push("\u2026"),Le(n.join(", "),op)}var zw=new Set(["file_path","notebook_path"]);function Kw(e,t){if(!t)return e;let n=i=>i.replace(/\\/g,"/").replace(/\/+$/,""),o=n(e),r=`${n(t)}/`;return(process.platform==="win32"?o.toLowerCase().startsWith(r.toLowerCase()):o.startsWith(r))?o.slice(r.length):e}var Rt=e=>typeof e=="string"&&e?e:null,Ia=e=>typeof e=="string"&&e.length>=8?e.slice(0,8):null;function Xw(e){let t=Rt(e)?.replace(/\\/g,"/");if(!t)return null;let n=t.split("/").filter(Boolean);if(n.length<2)return null;let o=n[n.length-2],r=o.replace(/^\d+[-_.]/,"").split(/[-_]/).filter(Boolean);return r.length===0?o:r.map(s=>s.charAt(0).toUpperCase()+s.slice(1)).join(" ")}function Qw(e,t){let n=(o,r)=>({title:`Document360: ${o}`,sep:" ",arg:r});switch(e){case"d360_create_article":{let o=Rt(t.title);if(!o)return null;let r=Xw(t.local_path);return n("Create article",`"${Le(o,60)}"${r?` in ${r}`:""}`)}case"d360_update_article":{let o=Rt(t.title),r=Ia(t.article_id);return n("Update article",o?`"${Le(o,60)}"`:r?`id ${r}\u2026`:null)}case"d360_fork_article":return n("Fork article (new draft)",Ia(t.article_id)?`id ${Ia(t.article_id)}\u2026`:null);case"d360_publish_article":{let o=t.version_number;return n("Publish article LIVE",typeof o=="number"?`v${o}`:null)}case"d360_unpublish_article":return n("Unpublish article",null);case"d360_create_category":return n("Create category",Rt(t.name)?`"${Le(Rt(t.name),60)}"`:null);case"d360_upload_drive_file":{let o=Rt(t.file_path);return n("Upload image",o?Le(o.replace(/\\/g,"/").split("/").pop()??o,60):null)}case"d360_sync_status":return n("Check sync status",null);default:return null}}function Xr(e,t,n){if(e==="ToolSearch")return null;if(e.startsWith("mcp__")){let[,s="",...i]=e.split("__"),c=i.join("__");if(s==="document360"){let b=Qw(c,t);if(b)return b}let p=c.replace(/^d360_/,"").replace(/_/g," ");return{title:`${s==="document360"?"Document360":s.charAt(0).toUpperCase()+s.slice(1)}: ${p}`,sep:" ",arg:np(t)}}let o=Yw[e],r=o?t[o]:void 0;if(typeof r=="string"&&r){let s=o&&zw.has(o)?Kw(r,n):r;return{title:e,sep:"",arg:Le(s,op)}}return{title:e,sep:"",arg:np(t)}}function Jw(e){if(e===null||typeof e!="object")return typeof e=="string"?e:null;let t=e;for(let n of["name","title","slug","id"])if(typeof t[n]=="string"&&t[n])return t[n];return null}function Zw(e){if(!/^[[{]/.test(e))return null;let t;try{t=JSON.parse(e)}catch{return null}if(Array.isArray(t)){let n=t.map(Jw).filter(r=>r!==null),o=`${t.length} item${t.length===1?"":"s"}`;return n.length===0?[o]:[o,...n.map(r=>Le(r,Oa))]}if(t!==null&&typeof t=="object"){let n=Object.entries(t).filter(([,o])=>o!==null&&(typeof o=="string"||typeof o=="number"||typeof o=="boolean")).slice(0,6).map(([o,r])=>`${o}: ${Le(String(r),rp)}`);return n.length>0?[Le(n.join(" \xB7 "),Oa)]:null}return null}function ek(e){let t=Rt(e)?.replace(/\\/g,"/");if(!t)return null;let n=t.split("/").filter(Boolean);return n.length>1?n.slice(1).join("/"):t}function tk(e,t,n){switch(e){case"d360_create_article":{let o=ek(t?.local_path);return[`\u2713 draft created${o?` \xB7 ${o}`:""}`]}case"d360_update_article":return["\u2713 draft updated"];case"d360_fork_article":return["\u2713 forked to a new draft"];case"d360_publish_article":return["\u2713 PUBLISHED LIVE \u2014 visible to readers"];case"d360_unpublish_article":return["\u2713 reverted to draft (removed from readers)"];case"d360_create_category":{let o=Rt(t?.name);return[`\u2713 category created${o?` \xB7 "${o}"`:""}`]}case"d360_upload_drive_file":{let o=n.match(/https?:\/\/\S+/);return[`\u2713 uploaded${o?` \xB7 ${Le(o[0],120)}`:""}`]}default:return null}}function Qr(e,t=4,n,o){let r=e.replace(/\r\n/g,`
|
|
382
382
|
`).trimEnd();if(!r)return{lines:["(no output)"],hidden:0};if(n?.startsWith("mcp__document360__")){let i=tk(n.slice(18),o,r);if(i)return{lines:i,hidden:0}}let s=Zw(r)??r.split(`
|
|
383
383
|
`);return{lines:s.slice(0,t).map(i=>Le(i,Oa)),hidden:Math.max(0,s.length-t)}}function Jr(e,t,n,o="en"){return`${e.replace(/\/$/,"")}/${t}/document/v1/${o}/${n}`}function Zr(e,t){if(typeof e.article_id=="string"&&e.article_id)return e.article_id;try{let n=JSON.parse(t),r=(Array.isArray(n)?n[0]:n)?.id;return typeof r=="string"&&r?r:null}catch{return null}}function sp(e,t){try{let n=JSON.parse(e),r=(Array.isArray(n)?n[0]:n)?.[t];return typeof r=="string"&&/^https?:\/\//.test(r)?r:null}catch{return null}}function es(e){return sp(e,"url")}function ts(e){return sp(e,"preview_url")}var $k=/^mcp__document360__d360_(create_article|update_article|fork_article|publish_article)$/;function vk(e,t,n,o){if($k.test(e))try{let r=cp(o),s=typeof t.project_id=="string"&&t.project_id||r.project.projectId,i=Zr(t,n),c=es(n);e.endsWith("publish_article")&&c&&console.log(W(` \u2B95 Live: ${c}`));let p=ts(n);p?console.log(W(` \u2B95 Preview: ${p}`)):i&&s&&console.log(W(` \u2B95 Preview: ${Jr(r.connection.portalUrl,s,i,r.project.languageCode??"en")}`))}catch{}}async function lp(e=process.cwd(),t="auto",n,o){let r=ok(t);r.kind==="none"&&(console.error(""),console.error(A("ANTHROPIC_API_KEY is not set (required for --auth api).")),console.error(""),console.error(` ${W("export ANTHROPIC_API_KEY=sk-ant-...")} (macOS / Linux)`),console.error(` ${W('$env:ANTHROPIC_API_KEY="sk-ant-..."')} (PowerShell)`),console.error(""),console.error(`Get a key at ${W("https://console.anthropic.com/settings/keys")}`),console.error(`Or use your Claude subscription instead: ${W("d360-writer --auth subscription")}`),console.error(""),process.exit(2)),xk(e,n),r.kind==="subscription"&&(r.stored?console.log(y(" Using your Claude subscription (no API key set).")):console.log(y(" No API key or stored Claude Code login found \u2014 trying your Claude session anyway.")),console.log(""));let s=!1,i=La({cwd:e,profileName:n,allowProdWrites:s}),c={uuid:null,firstPrompt:null,titleFired:!1},p=nk({input:process.stdin,output:process.stdout}),h=[],b=null,$=!1;p.on("line",R=>{if(b){let x=b;b=null,x(R)}else h.push(R)}),p.on("close",()=>{if($=!0,b){let R=b;b=null,R(null)}});function v(){return h.length>0?Promise.resolve(h.shift()):$?Promise.resolve(null):(process.stdout.write(W("> ")),new Promise(R=>{b=R}))}let E={cwd:e,version:o,profileName:n,allowProdWrites:()=>s,restartAgent:()=>{i.close(),i=La({cwd:e,profileName:n,allowProdWrites:s}),c={uuid:null,firstPrompt:null,titleFired:!1}},currentUuid:()=>c.uuid,setPendingName:R=>{c.pendingName=R},setModel:async R=>i.setModel(R),withPausedInput:async R=>{p.pause();try{return await R()}finally{p.resume()}}};try{for(;;){let R=await v();if(R===null)break;let x=R.trim();if(x){if(x.startsWith("/")){let T=Xu(x);if(!T)continue;let F=Ku[T.name];if(!F){console.log(A(`Unknown command: /${T.name}`)),console.log(y("Type /help for the list."));continue}let G=await F(T.args,E);if(G.kind==="exit")break;if(G.kind==="clear"){E.restartAgent();continue}if(G.kind==="allow-prod"){s=!0,E.restartAgent(),console.log(M("\u2713 Production writes authorized for this session.")),console.log("");continue}if(G.kind==="resume"){i.close(),i=La({cwd:e,resume:G.uuid,profileName:n,allowProdWrites:s});let q=rk(G.uuid);c={uuid:G.uuid,firstPrompt:q?.firstPrompt??null,titleFired:!0},ap(G.uuid),console.log(M(`\u2713 Resumed "${G.name}"`)),console.log("");continue}if(G.kind==="forward-to-agent"){c.firstPrompt||(c.firstPrompt=G.display??G.prompt);let q=(G.display??"").trim().split(/\s+/),Y=(q[0]==="/check"||q[0]==="/review")&&q.includes("--fix"),pe=q.slice(1).find(ae=>!ae.startsWith("--")),J=Y?kk(e,pe):[],re=q[0]==="/screenshot"&&(q[1]==="verify"||q[1]==="review"),le=re?q[2]&&!q[2].startsWith("--")?[q[2]]:co($e(e)):[];if(await _a(i,G.prompt,r,c,e),Y)try{wk(e,J,{reviewedCap:bk})}catch{}if(re&&le.length>0)try{for(let ae of uo(e,le))console.log(ae)}catch{}}else Ck(e,n);continue}if(fk(x)){let T=mk(x);if(T){try{gk(e,{title:T,by:"owner (d360-writer terminal)",at:new Date().toISOString()})}catch{}c.firstPrompt||(c.firstPrompt=x),await _a(i,`The owner left this documentation directive (already recorded in .d360-writer/directives.md): "${T}". Action it now: ground it in the sources, write/update the article(s) as DRAFTS (do not publish unless asked), following the active doc-type playbook. When finished, call d360_directive_done with the exact title "${T}" and the article path(s) you wrote.`,r,c,e);continue}}c.firstPrompt||(c.firstPrompt=x),await _a(i,x,r,c,e)}}}finally{i.close(),p.close()}}function xk(e,t){console.log(""),console.log(Vn("document360-writer")),console.log(y(` cwd: ${e}`));let n=lk(e);if(console.log(y(` model: ${n.model}${n.source==="auto"?" (auto \u2014 right-sized for docs; /model to change)":` (${n.source})`}`)),console.log(Rk(e,t)),!dk(e))console.log(B(" First run: /init (scaffolds config + prints the builder hand-off prompt) \u2192 /login, then ask me to write the docs."));else{let o=!1;try{if(sr(e),!it(e))for(let r of ir(e))console.log(B(` ${r}`))}catch{}try{let r=uk(e);r.persisted&&r.appType?console.log(y(` \u2713 Detected a ${r.appType} app \u2014 enabled the ${r.appType}-doc-playbook (change with /genre).`)):r.source==="unknown"&&(o=!0)}catch{}try{let r=yk(e);for(let s of or(r.applied))console.log(B(` ${s}`))}catch{}try{let r=ko(e,t,{claudeMissing:!1,allowAutoAudit:!1,genreUnknown:o}),s=r?wo(r):null;if(s?.kind==="recommend"&&s.rec.note){let i=s.rec.tone==="warn"?B:y;for(let c of Qs(s.rec.note).split(`
|
|
384
384
|
`))console.log(i(` ${c}`));s.rec.picker&&console.log(W(` Pick one: ${s.rec.picker.options.map(c=>c.cmd).join(" \xB7 ")}`))}}catch{}}console.log(y(" Type a prompt, or /help for slash commands. /exit to quit.")),console.log("")}function Ck(e,t){try{let n=ko(e,t,{claudeMissing:!1,allowAutoAudit:!1,genreUnknown:!1}),o=n?wo(n):null;o?.kind==="recommend"&&o.rec.lead&&console.log(y(` Next: ${yo(o.rec.lead)}`))}catch{}}function Rk(e,t){try{let n=cp(e,t),o=n.production?B(" \u26A0 PRODUCTION"):"",r=hk(n.name);if(!r)return y(` Document360: profile "${n.name}"${o} \u2014 not logged in (d360-writer login)`);let s={...ip(r.idToken)??{},...ip(r.accessToken)??{}},i=s.email??s.preferred_username??"signed in";return pk(r)&&!r.refreshToken?B(` Document360: profile "${n.name}"${o} \u2014 session expired (d360-writer login)`):y(` Document360: ${i} \xB7 profile "${n.name}"${o}`)}catch(n){return y(` Document360: ${n.message.split(".")[0]}`)}}function Sk(){console.error(""),console.error(`Sign in with your Claude subscription: run ${W("claude")} once, then retry.`),console.error(` (No Claude Code? ${W("npm install -g @anthropic-ai/claude-code")})`),console.error(`Or set an API key: ${W("https://console.anthropic.com/settings/keys")}`)}function Pk(e,t,n){e.uuid=t;let o=new Date().toISOString(),r=e.pendingName;ak({uuid:t,name:r??ik(e.firstPrompt??"session"),renamed:!!r,titled:!1,cwd:n,firstPrompt:e.firstPrompt??"",createdAt:o,updatedAt:o}),e.pendingName=null}function Tk(e,t){e.titleFired=!0;let n=e.uuid,o=e.firstPrompt;!n||!o||ck(o,t).then(r=>{r&&sk(n,r)}).catch(()=>{})}async function _a(e,t,n,o,r){let s=new Map;for await(let i of e.send(t))Ek(i,o,r,n,s)}function Ek(e,t,n,o,r){switch(e.type){case"session":t.uuid||Pk(t,e.sessionId,n);break;case"text":process.stdout.write(e.delta);break;case"tool":{let s=Xr(e.name,e.input,process.cwd());s&&(process.stdout.write(`
|
package/package.json
CHANGED