document360-writer 0.4.74 → 0.4.75

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/dist/cli.js +1 -1
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -244,7 +244,7 @@ Articles:
244
244
  ${Ud}
245
245
  Run /doctor anytime to re-check and see the fix. (You can configure Document360 meanwhile \u2014 the agent just needs Claude before it writes.)`}),!Q(e)){u({kind:"note",tone:"info",text:`Welcome! This repo isn't set up for d360-writer yet \u2014 three steps and you're writing docs:
246
246
  ${va}`}),V(l?["/doctor","/init"]:["/init"]);return}l&&V(["/doctor"]);try{let i=fe(e,s),a=Ke(i.name);a&&Oe(a)&&a.refreshToken?Wd({profile:i.name,connection:i.connection}).then(()=>{u({kind:"note",tone:"ok",text:"\u2713 Document360 session refreshed."}),oe(g=>g+1)}).catch(()=>{u({kind:"note",tone:"warn",text:"Document360 session refresh failed \u2014 do you want to log in now? (press 1)"}),V(["/login"])}):(!a||Oe(a))&&(u({kind:"note",tone:"warn",text:`Profile "${i.name}" is not signed in \u2014 do you want to log in now? (press 1)`}),V(["/login"]))}catch{}try{let i=Q(e),a=fe(e,s),g=Ke(a.name);i&&g&&!Oe(g)&&yp(e,i.authoritativeSourceFiles)&&(u({kind:"note",tone:"info",text:"Large repo \u2014 the docs scope isn\u2019t set yet. Run /scope to choose which folders back your docs."}),V(["/scope"]))}catch{}try{yn(e);let i=kn(e);i.length&&(u({kind:"note",tone:"warn",text:i.join(`
247
- `)}),pt(Ve()),St.current=!1)}catch{}try{let i=$t(xt(e));i&&(u({kind:"note",tone:"info",text:`\u{1F4CB} ${i} from the repo's coding agent \u2014 press 1 to /catch-up.`}),V(a=>a.includes("/catch-up")?a:[...a,"/catch-up"]))}catch{}try{up(cp())&&Q(e)?.mode!=="engineer"&&lp({pkg:Xe,currentVersion:o}).then(async i=>{if(!i.updateAvailable||!i.latest)return;u({kind:"note",tone:"info",text:`\u2B06 Updating ${Xe} ${i.current} \u2192 ${i.latest}\u2026`}),(await In()).ok?(u({kind:"note",tone:"ok",text:`\u2713 Updated to v${i.latest} \u2014 /exit and relaunch to apply (press 1).`}),V(g=>g.includes("/exit")?g:[...g,"/exit"])):u({kind:"note",tone:"warn",text:`Update available (v${i.latest}) but auto-update failed \u2014 run: ${En}`})}).catch(()=>{})}catch{}},[]),Se(()=>{let l=null,i=null,a=()=>{l&&clearTimeout(l),l=setTimeout(()=>{l=null;let g=`${be.columns??80}x${be.rows??24}`;g!==Wr.current&&(Wr.current=g,Ma(d=>d+1),i&&clearTimeout(i),i=setTimeout(()=>{i=null,console.log("\x1B[?2026h\x1B[H\x1B[2J"+Fs(tt.current,Ae())+"\x1B[?2026l")},80))},400)};return be.on("resize",a),()=>{l&&clearTimeout(l),i&&clearTimeout(i),be.off("resize",a)}},[be,Ae]);let Ge=Math.max(20,(be.columns??80)-1),Fr=Cr(()=>mp(e,s),[e,s,$e]),no=(()=>{let l=Q(e);if(!l)return{text:"Press 1 to set up this repo, or /help\u2026",isSetup:!0};let i=Gt(e,(l.docsDir??Da).replace(/\/+$/,"")),a=(()=>{try{return Gn(i)&&Sa(i).length>0}catch{return!1}})();try{let g=fe(e,s),d=Ke(g.name);if(!(!!d&&!(Oe(d)&&!d.refreshToken)))return{text:`Press 1 to sign in to Document360 (profile "${g.name}")\u2026`,isSetup:!0};if(!g.project.workspaceId&&!a)return{text:"Press 1 to pick a workspace\u2026",isSetup:!0}}catch{}return a?{text:hp,isSetup:!1}:eo?{text:"Press c to copy the prompt above, run it in your coding agent \u2014 then ask me to write the docs",isSetup:!1}:{text:"Ask me to write the docs for this repo",isSetup:!1}})(),Rt=fs(D),Hr=Rt.length>0&&!E,oo=p!==null?ha(p,8,Ge):null,Qt=ge?ge.paths.filter(l=>!ge.query||l.toLowerCase().includes(ge.query.toLowerCase())).slice(0,8):[],Zt=ye?ye.sessions.filter(l=>{let i=ye.query.toLowerCase();return!i||l.name.toLowerCase().includes(i)||l.firstPrompt.toLowerCase().includes(i)}).slice(0,8):[],ue=G((l,i)=>{me.current?.close(),me.current=ya({cwd:e,resume:l,profileName:i??s,allowProdWrites:nt.current}),l||(ve.current={uuid:null,firstPrompt:null,titleFired:!1},ot(null)),ut(0),dt(0)},[e,s]),qr=G((l,i,a)=>{if(gp.test(l))try{let g=fe(e,s),d=typeof i.project_id=="string"&&i.project_id||g.project.projectId,m=Mn(i,a),y=[],T=Ln(a);l.endsWith("publish_article")&&T&&y.push(`Live: ${T}`),m&&d&&y.push(`Preview: ${On(g.connection.portalUrl,d,m,g.project.languageCode??"en")}`),y.length>0&&u({kind:"link",lines:y})}catch{}},[e,s,u]),de=G(async(l,i)=>{Vt(!0),se(null),V([]),Xt(null),to(null);let a=++Je.current;i?.quietUser||u({kind:"user",text:i?.echoDisplay&&i.display?i.display:l});let g=ve.current;g.firstPrompt||(g.firstPrompt=i?.display??l),Me.current=Date.now(),Qe(0),_(!0),zt.current.clear();let d="",m=!1,y=!1,T="",I=null,N=()=>{I||(I=setTimeout(()=>{I=null,h(T.length>0?T:null)},60))},re=()=>{I&&clearTimeout(I),I=null,h(null)},Y=()=>{if(T.trim()){let $=T.trimEnd();u({kind:"assistant",text:$})}T="",re()};try{for await(let $ of me.current.send(l))if($.type==="session"){if(!g.uuid){g.uuid=$.sessionId;let P=new Date().toISOString(),U=Vd(g.firstPrompt??"session");Yd({uuid:$.sessionId,name:U,renamed:!1,titled:!1,cwd:e,firstPrompt:g.firstPrompt??"",createdAt:P,updatedAt:P}),ot(U)}}else if($.type==="text"){T+=$.delta,d+=$.delta;let P=ga(T);if(P>0){let U=T.slice(0,P).trimEnd();U&&u({kind:"assistant",text:U}),T=T.slice(P)}N(),Qe(U=>U+$.delta.length)}else if($.type==="tool"){m=!0;let P=_n($.name,$.input);P&&(Y(),u({kind:"tool",title:P.title,sep:P.sep,arg:P.arg}),zt.current.set($.id,{name:$.name,input:$.input}))}else if($.type==="article_diff"){let P=ze($.oldContent,$.newContent,Ae());P&&(Y(),u({kind:"diff",added:P.added,removed:P.removed,lines:P.lines,hidden:P.hidden}))}else if($.type==="tool_result"){$.isError&&/run \/login|not logged in|session expired|rejected the token/i.test($.output)&&(Kt.current=!0);let P=zt.current.get($.id);if(P){zt.current.delete($.id),Y();let U=Un($.output,4,$.isError?void 0:P.name,P.input);u({kind:"tool-result",lines:U.lines,hidden:U.hidden,isError:$.isError}),$.isError||qr(P.name,P.input,$.output)}}else if($.type==="result"){Y(),ut(U=>U+$.outputTokens),dt(U=>U+$.costUsd),u({kind:"done",seconds:Math.round((Date.now()-Me.current)/1e3),tokens:$.outputTokens,costUsd:$.costUsd,ok:$.ok}),!y&&!m&&!d.trim()&&!Tt.current&&u({kind:"note",tone:"warn",text:"The agent produced no output. This usually means the Claude model/runtime did not start \u2014 check sign-in and model with /doctor (on a subscription, make sure Claude Code is logged in on this machine)."});let P=$.ok?sa(d,It.map(U=>U.name)):[];if(P.length>0?V(P):$.ok&&d.trim()&&Jd(l,d,e).then(U=>{U&&Je.current===a&&se(U)}).catch(()=>{}),g.uuid&&(Pr(g.uuid),!g.titleFired)){g.titleFired=!0;let U=g.uuid,Z=g.firstPrompt;Z&&ka(Z,e).then(O=>{O&&(Gd(U,O),ot(O))}).catch(()=>{})}}else $.type==="error"&&(Y(),y=!0,$.kind==="auth"&&(Kt.current=!0),u({kind:"note",text:`agent error: ${$.message}`,tone:"error"}))}finally{_(!1),re(),oe($=>$+1),ve.current.uuid&&oa(e,ve.current.uuid,tt.current),Kt.current&&(Kt.current=!1,Jt.current=i?.display??l,V(["/login"])),Tt.current&&(Tt.current=!1,qe.current.length>0&&(u({kind:"note",tone:"info",text:`(${qe.current.length} queued message(s) discarded)`}),qe.current=[],Qn([])),u({kind:"note",tone:"warn",text:"Interrupted. What do you want to do next?"}))}},[e,u,qr,Ae]),en=G(async l=>{let i=Sr(l),a=Yn(e,"standard");Me.current=Date.now(),Qe(0),_(!0);let g=new AbortController;we.current=g,X({verb:"Publishing",total:i.length,done:0,active:[],rows:qt(i),tools:0,chars:0,lastAt:Date.now(),startedAt:Date.now()}),u({kind:"note",tone:"info",text:`Publishing ${l.length} article${l.length===1?"":"s"} across ${i.length} partition${i.length===1?"":"s"} (\u2264${Ot} agents at once) on ${a.model}\u2026 (esc to stop)`});try{for await(let d of Vn({cwd:e,partitions:i,promptFor:m=>vn(m.paths),concurrency:Ot,profileName:s,allowProdWrites:nt.current,model:a.model,signal:g.signal}))if(d.type==="partition_status")d.status==="running"?X(m=>m&&{...m,active:[...m.active,d.label],rows:Te(m.rows,d.label,"active"),lastAt:Date.now()}):X(m=>m&&{...m,active:m.active.filter(y=>y!==d.label),done:m.done+1,rows:Te(m.rows,d.label,d.status==="done"?"done":"failed"),lastAt:Date.now()});else if(d.type==="partition_event")X(m=>{if(!m)return m;let y={...m,lastAt:Date.now()};return d.event.type==="tool"?y.tools=m.tools+1:d.event.type==="text"&&(y.chars=m.chars+d.event.delta.length),y});else if(d.type==="run_done"){dt(T=>T+d.totalCostUsd),ut(T=>T+d.results.reduce((I,N)=>I+N.outputTokens,0));let m=d.aborted?"Stopped. ":"",y=t.kind==="api"?"api":"subscription";u({kind:"note",tone:d.aborted?"warn":d.ok?"ok":"warn",text:m+jo(d.results,i,y).join(`
247
+ `)}),pt(Ve()),St.current=!1)}catch{}try{let i=$t(xt(e));i&&(u({kind:"note",tone:"info",text:`\u{1F4CB} ${i} from the repo's coding agent \u2014 press 1 to /catch-up.`}),V(a=>a.includes("/catch-up")?a:[...a,"/catch-up"]))}catch{}try{up(cp())&&Q(e)?.mode!=="engineer"&&lp({pkg:Xe,currentVersion:o}).then(async i=>{if(!i.updateAvailable||!i.latest)return;u({kind:"note",tone:"info",text:`\u2B06 Updating ${Xe} ${i.current} \u2192 ${i.latest}\u2026`}),(await In()).ok?(u({kind:"note",tone:"ok",text:`\u2713 Updated to v${i.latest} \u2014 /exit and relaunch to apply (press 1).`}),V(g=>g.includes("/exit")?g:[...g,"/exit"])):u({kind:"note",tone:"warn",text:`Update available (v${i.latest}) but auto-update failed \u2014 run: ${En}`})}).catch(()=>{})}catch{}},[]),Se(()=>{let l=null,i=null,a=()=>{l&&clearTimeout(l),l=setTimeout(()=>{l=null;let g=`${be.columns??80}x${be.rows??24}`;g!==Wr.current&&(Wr.current=g,Ma(d=>d+1),i&&clearTimeout(i),i=setTimeout(()=>{i=null,console.log("\x1B[?2026h\x1B[H\x1B[2J"+Fs(tt.current,Ae())+"\x1B[?2026l")},80))},400)};return be.on("resize",a),()=>{l&&clearTimeout(l),i&&clearTimeout(i),be.off("resize",a)}},[be,Ae]);let Ge=Math.max(20,(be.columns??80)-1),Fr=Cr(()=>mp(e,s),[e,s,$e]),no=(()=>{let l=Q(e);if(!l)return{text:"Press 1 to set up this repo, or /help\u2026",isSetup:!0};let i=Gt(e,(l.docsDir??Da).replace(/\/+$/,"")),a=(()=>{try{return Gn(i)&&Sa(i).length>0}catch{return!1}})();try{let g=fe(e,s),d=Ke(g.name);if(!(!!d&&!(Oe(d)&&!d.refreshToken)))return{text:`Press 1 to sign in to Document360 (profile "${g.name}")\u2026`,isSetup:!0};if(!g.project.projectId)return{text:"Sign in to Document360 to pick your project\u2026",isSetup:!0};if(!g.project.workspaceId&&!a)return{text:"Press 1 to pick a workspace\u2026",isSetup:!0}}catch{}return a?{text:hp,isSetup:!1}:eo?{text:"Press c to copy the prompt above, run it in your coding agent \u2014 then ask me to write the docs",isSetup:!1}:{text:"Ask me to write the docs for this repo",isSetup:!1}})(),Rt=fs(D),Hr=Rt.length>0&&!E,oo=p!==null?ha(p,8,Ge):null,Qt=ge?ge.paths.filter(l=>!ge.query||l.toLowerCase().includes(ge.query.toLowerCase())).slice(0,8):[],Zt=ye?ye.sessions.filter(l=>{let i=ye.query.toLowerCase();return!i||l.name.toLowerCase().includes(i)||l.firstPrompt.toLowerCase().includes(i)}).slice(0,8):[],ue=G((l,i)=>{me.current?.close(),me.current=ya({cwd:e,resume:l,profileName:i??s,allowProdWrites:nt.current}),l||(ve.current={uuid:null,firstPrompt:null,titleFired:!1},ot(null)),ut(0),dt(0)},[e,s]),qr=G((l,i,a)=>{if(gp.test(l))try{let g=fe(e,s),d=typeof i.project_id=="string"&&i.project_id||g.project.projectId,m=Mn(i,a),y=[],T=Ln(a);l.endsWith("publish_article")&&T&&y.push(`Live: ${T}`),m&&d&&y.push(`Preview: ${On(g.connection.portalUrl,d,m,g.project.languageCode??"en")}`),y.length>0&&u({kind:"link",lines:y})}catch{}},[e,s,u]),de=G(async(l,i)=>{Vt(!0),se(null),V([]),Xt(null),to(null);let a=++Je.current;i?.quietUser||u({kind:"user",text:i?.echoDisplay&&i.display?i.display:l});let g=ve.current;g.firstPrompt||(g.firstPrompt=i?.display??l),Me.current=Date.now(),Qe(0),_(!0),zt.current.clear();let d="",m=!1,y=!1,T="",I=null,N=()=>{I||(I=setTimeout(()=>{I=null,h(T.length>0?T:null)},60))},re=()=>{I&&clearTimeout(I),I=null,h(null)},Y=()=>{if(T.trim()){let $=T.trimEnd();u({kind:"assistant",text:$})}T="",re()};try{for await(let $ of me.current.send(l))if($.type==="session"){if(!g.uuid){g.uuid=$.sessionId;let P=new Date().toISOString(),U=Vd(g.firstPrompt??"session");Yd({uuid:$.sessionId,name:U,renamed:!1,titled:!1,cwd:e,firstPrompt:g.firstPrompt??"",createdAt:P,updatedAt:P}),ot(U)}}else if($.type==="text"){T+=$.delta,d+=$.delta;let P=ga(T);if(P>0){let U=T.slice(0,P).trimEnd();U&&u({kind:"assistant",text:U}),T=T.slice(P)}N(),Qe(U=>U+$.delta.length)}else if($.type==="tool"){m=!0;let P=_n($.name,$.input);P&&(Y(),u({kind:"tool",title:P.title,sep:P.sep,arg:P.arg}),zt.current.set($.id,{name:$.name,input:$.input}))}else if($.type==="article_diff"){let P=ze($.oldContent,$.newContent,Ae());P&&(Y(),u({kind:"diff",added:P.added,removed:P.removed,lines:P.lines,hidden:P.hidden}))}else if($.type==="tool_result"){$.isError&&/run \/login|not logged in|session expired|rejected the token/i.test($.output)&&(Kt.current=!0);let P=zt.current.get($.id);if(P){zt.current.delete($.id),Y();let U=Un($.output,4,$.isError?void 0:P.name,P.input);u({kind:"tool-result",lines:U.lines,hidden:U.hidden,isError:$.isError}),$.isError||qr(P.name,P.input,$.output)}}else if($.type==="result"){Y(),ut(U=>U+$.outputTokens),dt(U=>U+$.costUsd),u({kind:"done",seconds:Math.round((Date.now()-Me.current)/1e3),tokens:$.outputTokens,costUsd:$.costUsd,ok:$.ok}),!y&&!m&&!d.trim()&&!Tt.current&&u({kind:"note",tone:"warn",text:"The agent produced no output. This usually means the Claude model/runtime did not start \u2014 check sign-in and model with /doctor (on a subscription, make sure Claude Code is logged in on this machine)."});let P=$.ok?sa(d,It.map(U=>U.name)):[];if(P.length>0?V(P):$.ok&&d.trim()&&Jd(l,d,e).then(U=>{U&&Je.current===a&&se(U)}).catch(()=>{}),g.uuid&&(Pr(g.uuid),!g.titleFired)){g.titleFired=!0;let U=g.uuid,Z=g.firstPrompt;Z&&ka(Z,e).then(O=>{O&&(Gd(U,O),ot(O))}).catch(()=>{})}}else $.type==="error"&&(Y(),y=!0,$.kind==="auth"&&(Kt.current=!0),u({kind:"note",text:`agent error: ${$.message}`,tone:"error"}))}finally{_(!1),re(),oe($=>$+1),ve.current.uuid&&oa(e,ve.current.uuid,tt.current),Kt.current&&(Kt.current=!1,Jt.current=i?.display??l,V(["/login"])),Tt.current&&(Tt.current=!1,qe.current.length>0&&(u({kind:"note",tone:"info",text:`(${qe.current.length} queued message(s) discarded)`}),qe.current=[],Qn([])),u({kind:"note",tone:"warn",text:"Interrupted. What do you want to do next?"}))}},[e,u,qr,Ae]),en=G(async l=>{let i=Sr(l),a=Yn(e,"standard");Me.current=Date.now(),Qe(0),_(!0);let g=new AbortController;we.current=g,X({verb:"Publishing",total:i.length,done:0,active:[],rows:qt(i),tools:0,chars:0,lastAt:Date.now(),startedAt:Date.now()}),u({kind:"note",tone:"info",text:`Publishing ${l.length} article${l.length===1?"":"s"} across ${i.length} partition${i.length===1?"":"s"} (\u2264${Ot} agents at once) on ${a.model}\u2026 (esc to stop)`});try{for await(let d of Vn({cwd:e,partitions:i,promptFor:m=>vn(m.paths),concurrency:Ot,profileName:s,allowProdWrites:nt.current,model:a.model,signal:g.signal}))if(d.type==="partition_status")d.status==="running"?X(m=>m&&{...m,active:[...m.active,d.label],rows:Te(m.rows,d.label,"active"),lastAt:Date.now()}):X(m=>m&&{...m,active:m.active.filter(y=>y!==d.label),done:m.done+1,rows:Te(m.rows,d.label,d.status==="done"?"done":"failed"),lastAt:Date.now()});else if(d.type==="partition_event")X(m=>{if(!m)return m;let y={...m,lastAt:Date.now()};return d.event.type==="tool"?y.tools=m.tools+1:d.event.type==="text"&&(y.chars=m.chars+d.event.delta.length),y});else if(d.type==="run_done"){dt(T=>T+d.totalCostUsd),ut(T=>T+d.results.reduce((I,N)=>I+N.outputTokens,0));let m=d.aborted?"Stopped. ":"",y=t.kind==="api"?"api":"subscription";u({kind:"note",tone:d.aborted?"warn":d.ok?"ok":"warn",text:m+jo(d.results,i,y).join(`
248
248
  `)})}}catch(d){u({kind:"note",tone:"error",text:`Publish run failed: ${d.message}`})}finally{we.current=null,X(null),_(!1),oe(d=>d+1)}},[e,s,u,t]),ro=G(async l=>{await de(Do(l),{display:`/publish ${l}`,quietUser:!0});try{let i=await Cn(e,s,l.replace(/\\/g,"/"));i.length>0&&(Xt(`Related articles not yet published (${i.length}):`),V([`/publish --related ${l}`,...i.map(a=>`/publish ${a}`)]))}catch{}},[e,s,de]),so=G(l=>{let i=Ke(l);if(!i||Oe(i)&&!i.refreshToken)return null;let a={...vt(i.idToken)??{},...vt(i.accessToken)??{}};return a.email??a.preferred_username??"signed in"},[]),io=G((l,i)=>{if(i){let a=Q(e);a&&(a.defaultProfile=l,Qd(a,e))}c(l),ue(void 0,l),u({kind:"note",tone:"ok",text:`\u2713 Switched to profile "${l}"${i?" (saved as default)":" (this session only)"} \u2014 agent restarted.`}),so(l)||(u({kind:"note",tone:"warn",text:`Profile "${l}" is not signed in \u2014 do you want to log in now? (press 1)`}),V(["/login"])),oe(a=>a+1)},[e,u,ue,so]),tn=G((l,i,a)=>{an(e,l,i,a.id,a.name),u({kind:"note",tone:"ok",text:`Switched to workspace "${a.name??a.id}" (agent restarted).`}),ue(),ba(e,l)||(u({kind:"note",tone:"ok",text:"\u2713 Connected. Configuration is done \u2014 one important step remains."}),u({kind:"note",tone:"warn",text:"\u26A0 Before I write the docs, hand the prompt below to your builder (your repo's coding agent). It gives me the architecture brief that makes the docs accurate:"}),u({kind:"note",tone:"info",text:yt(wt(e)).join(`
249
249
  `)}),pt(Ve()),St.current=Ie(e).status==="current",u({kind:"note",tone:"info",text:`No separate builder agent? Then just ask me now: "write the docs for this repo" \u2014 I'll read the code directly.`}))},[e,u,ue,pt]),nn=G(async l=>{let i;try{i=await At(e,l)}catch{u({kind:"note",tone:"info",text:"Next: pick a workspace \u2014 run /workspace."}),V(["/workspace"]);return}if(i.workspaces.length===0){u({kind:"note",tone:"warn",text:"This project has no workspaces yet. Create one in Document360, then run /workspace."});return}let a=i.workspaces.filter(d=>(d.workspace_type??"").toLowerCase()!=="apidocumentation"),g=a.length>0?a:i.workspaces;if(g.length===1){let d=g[0],m=i.workspaces.length-g.length;u({kind:"note",tone:"ok",text:`Selected the "${d.name??d.id}" workspace${m>0?" (skipped the API-documentation workspace)":""}.`}),tn(i.profile,i.projectId,d);return}u({kind:"note",tone:"info",text:`Next: pick the workspace your articles publish to (${g.length} available).`}),V(["/workspace"])},[e,u,tn]),Br=G((l,i)=>{po(e,l,i.id,i.name),u({kind:"note",tone:"ok",text:`Project set to "${i.name??i.id}" (agent restarted).`}),ue(),nn(l)},[e,u,ue,nn]),Gr=G(async l=>{let i;try{i=fe(e,l)}catch{return}if(!i.project.workspaceId){if(i.project.projectId){if(!i.project.projectName)try{let{projects:a}=await ht(e,i.name),g=a.find(d=>d.id===i.project.projectId);g?.name&&dp(e,i.name,{projectName:g.name})}catch{}await nn(i.name);return}u({kind:"note",tone:"info",text:"Next: pick the Document360 project."}),V(["/project"])}},[e,u,nn]),on=G(()=>{let l=De.current[0];if(!l)return;u({kind:"note",tone:"info",text:`\u25CF ${l.title} (${l.path})`});for(let a of l.notes)u({kind:"note",tone:"warn",text:`\u26A0 ${a}`});l.overwritesLocalChanges&&u({kind:"note",tone:"warn",text:"\u26A0 This OVERWRITES local edits made since the last sync."});let i=ze(l.oldContent,l.newContent,Ae());u(i?{kind:"diff",added:i.added,removed:i.removed,lines:i.lines,hidden:i.hidden}:{kind:"note",tone:"info",text:"Local file already matches the remote content \u2014 applying only advances the sync base."}),u({kind:"note",tone:"info",text:`Write ${l.path}? (y/n \u2014 anything else cancels)`})},[u,Ae]),Vr=G(l=>{if(De.current.length===0)return!1;let i=l.trim().toLowerCase();if(i==="y"||i==="yes"){let a=De.current.shift();try{Zd({cwd:e,profileName:s},a),u({kind:"note",tone:"ok",text:`\u2713 Pulled ${a.path} (sync base advanced).`}),De.current.length===0&&V(g=>g.length>0?g:["/sync"])}catch(g){u({kind:"note",tone:"error",text:`Pull failed: ${g.message}`})}}else if(i==="n"||i==="no"){let a=De.current.shift();u({kind:"note",tone:"info",text:`Skipped ${a.path}.`})}else{let a=De.current.length;return De.current=[],u({kind:"note",tone:"info",text:`Pull cancelled (${a} article(s) left untouched).`}),!0}return on(),!0},[e,s,on,u]),Yr=G(l=>{let i=Jn.current;if(!i)return!1;if(Jn.current=null,se(null),Je.current++,l.trim()!==i.repoName)return u({kind:"note",tone:"warn",text:"Reset cancelled \u2014 nothing deleted."}),!0;let{removed:a,failed:g}=hr(e,i.targets);u({kind:"note",tone:g.length?"warn":"ok",text:`\u2713 Reset complete \u2014 removed ${a.length} item${a.length===1?"":"s"}. The repo is back to its original state.`});for(let d of g)u({kind:"note",tone:"error",text:` \u2717 ${d.path}: ${d.error}`});return i.hadDevhints&&(u({kind:"note",tone:"warn",text:bn().join(`
250
250
  `)}),pt(yo())),u({kind:"note",tone:"info",text:`Clean slate \u2014 set up d360-writer again whenever you're ready:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document360-writer",
3
- "version": "0.4.74",
3
+ "version": "0.4.75",
4
4
  "description": "Standalone documentation agent CLI. Reads your code, writes your docs. Specialized for Document360 publishing.",
5
5
  "type": "module",
6
6
  "bin": {