document360-writer 0.5.39 → 0.5.40
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 +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -245,7 +245,7 @@ Articles:
|
|
|
245
245
|
`),display:"/capture-setup"}}var Sa="-".repeat(64);function Yr(e){let t=np;try{let x=tp(e);x?.captureDir&&(t=x.captureDir.replace(/\\/g,"/").replace(/\/+$/,""))}catch{}let n=Qd(t)?Zd(t,"CAPTURE-TESTID-REQUESTS.json"):ep(e,t,"CAPTURE-TESTID-REQUESTS.json");if(!Xd(n))return null;let o;try{let x=JSON.parse(Jd(n,"utf8").replace(/^/,""));o=Array.isArray(x?.requests)?x.requests:[]}catch{return null}if(o.length===0)return null;let r=new Set(o.map(x=>x.file).filter(Boolean)).size,s=o.length,c=`${s} data-testid attribute${s===1?"":"s"}`,p=`${r} source file${r===1?"":"s"}`,h=`${t}/CAPTURE-TESTID-REQUESTS.md`,b=`${t}/CAPTURE-TESTID-REQUESTS.json`;return[`\u{1F4CB} Developer hand-off \u2014 ${c} requested across ${p}.`,"\u26A0 Do NOT run this prompt here. d360-writer documents code; it does not change it \u2014"," these edits belong in your code repo. Open a SEPARATE terminal in:",` ${e}`," start Claude Code (or your coding agent), and paste everything between the lines."," Tip: run it in plan mode first \u2014 these are a hypothesis to verify, not a verified patch.","",Sa,`Read ${h} and ${b}. They list ${c} that d360-writer THINKS this repo needs for screenshot automation. Treat them as a hypothesis to VERIFY against the source \u2014 not a verified patch list.`,"","For EACH request in the JSON:",'1. Locate the element in THIS repo. Trace it from the route/page, not the feature name. If "anchorVerified" is false, find it by the "element"/"reason" description; otherwise confirm the "anchor" snippet still exists in "file".',"2. If the element already has a data-testid, skip it and note the existing one.","3. Confirm the attribute will reach the DOM: the rendering component must forward unknown props (a {...rest} spread or explicit pass-through). If it is a shared wrapper (e.g. Modal, ContextMenu) that destructures a fixed prop list, a data-testid is silently dropped \u2014 thread it through the component, or report it as needing a code change instead of forcing it.",'4. Only then add data-testid="<testid>" to the verified element. Add nothing else; do not rename, restructure, reformat, or change behaviour.',"","When done, report: which testids you added (file + element), which were already present, which requests were wrong (wrong file/anchor/page) with the correction, and which need threading through a shared component. Never force a request that does not match the source \u2014 flag it instead.",Sa]}at();W();import{listOpenForDocs as op,readProjectConfig as rp}from"document360-engine";function Gr(e){try{return op(e).length}catch{return 0}}function Vr(){return["Process the two-way message inbox from the source repo's coding agent (the builder).","","1. Call d360_inbox to list the OPEN messages addressed to you.","2. For each message, act by its kind:",' \u2022 request ("document the X we shipped") \u2192 treat it as a session hand-off: run the document-handoff'," skill \u2014 read what changed, ground it in the cited sources + the architecture brief, then decide and"," apply the RIGHT doc action (new section, new article, update existing, or retire). No fixed shape."," \u2022 answer (a reply to a question you asked; `re` = your question id) \u2192 fold the fact into the affected"," article(s), and into `.d360-writer/architecture/` if it is durable product knowledge.","3. After acting on a message, mark it resolved: edit its file in `.d360-writer/messages/` and set the"," frontmatter `status: done` (add `done_at` with the current UTC time). Never delete the file.","4. Drafts only \u2014 do not publish unless explicitly asked. End with a one-line summary of what you did per"," message (and, for any request you could not fully ground, what you still need)."].join(`
|
|
246
246
|
`)}async function Da(e,t){let n=t?.cwd??process.cwd();return rp(n)?Gr(n)===0?(console.log(f("Inbox empty \u2014 no open messages from the builder. (They arrive via the builder's /devhints hand-off.)")),{kind:"continue"}):{kind:"forward-to-agent",prompt:Vr(),display:"/inbox"}:(console.log(v("No d360-writer config here. Run /init first.")),{kind:"continue"})}W();import{listOpenHints as sp,listOpenForDocs as ip,readProjectConfig as ap,computeSyncStatus as lp,planPull as cp,applyPull as up}from"document360-engine";function Nt(e){let t=0,n=0,o=0;try{t=sp(e).length}catch{}try{let r=ip(e);n=r.filter(s=>s.kind==="request").length,o=r.filter(s=>s.kind==="answer").length}catch{}return{hints:t,requests:n,answers:o}}function _t(e){let t=[];return e.hints&&t.push(`${e.hints} hint${e.hints===1?"":"s"}`),e.requests&&t.push(`${e.requests} request${e.requests===1?"":"s"}`),e.answers&&t.push(`${e.answers} answer${e.answers===1?"":"s"}`),t.length?t.join(", "):null}function Kr(e){return{publish:e.includes("--publish")}}function Xr({publish:e}){let t=["Catch the documentation up: process ALL the pending work the builder has queued, end to end.","","1. The portal was already reconciled before this run: clean portal edits were pulled into local, and any conflicts / new-portal-articles were surfaced to the user. Do NOT re-pull. Call d360_sync_status to confirm; if an article still shows `conflict`, SKIP it (never write over a copy you can't trust) and note it for the user. Otherwise proceed.","2. Gather the pending work: d360_pending_hints (the builder's per-change hints) AND d360_inbox (open requests + answers).","3. Decide the right doc actions across all of it: gap-analysis for the hints (verify each against its sources + commit), document-handoff for each request (no fixed shape \u2014 new section / new article / update / retire), and fold any answers into the affected article(s) + the architecture brief.","4. If that means writing more than one article, call d360_estimate_cost and show me the count + cost band first (the bulk gate), then proceed.","5. Write/update the articles as drafts, grounded in the cited sources.","6. Close the loop: stamp consumed hints, and mark handled messages status: done with resulting_articles.","7. Push the drafts to Document360.","8. Cross-link second pass: any article you wrote that links to ANOTHER article in this same batch had that inline link degrade to plain text (its target had no live URL yet when the source was written). Now that every target exists, re-update the affected articles so those inline links resolve to live URLs \u2014 only the ones that had such forward references need it. (The structured Related Articles sidebars are already two-way linked; this is just inline body links.)"];return t.push(e?"9. Then publish the new/updated articles live (publish-to-d360 skill), respecting the production write-guard.":"Leave everything as DRAFTS for review \u2014 do not publish live (run /publish when you want them live)."),t.push("","End with a one-line-per-item summary of what you wrote/updated, and anything you couldn't ground (plus the d360_ask_builder question you left for it)."),t.join(`
|
|
247
247
|
`)}var dp={status:lp,plan:cp,apply:up};async function Jr(e,t=dp){let n={pulled:[],conflicts:[],untrackedRemote:[],failed:[]},o;try{o=await t.status({cwd:e.cwd,profileName:e.profileName})}catch(r){return n.error=r.message,n}for(let r of o.entries)if(r.status==="conflict"&&r.path)n.conflicts.push(r.path);else if(r.status==="untracked-remote")n.untrackedRemote.push(r.title??r.articleId??"(untitled)");else if(r.status==="remote-ahead"&&r.path)try{let s=await t.plan({cwd:e.cwd,profileName:e.profileName,relPath:r.path});t.apply({cwd:e.cwd,profileName:e.profileName},s),n.pulled.push(r.path)}catch(s){n.failed.push({path:r.path,error:s.message})}return n}var zr=(e,t=5)=>`${e.slice(0,t).join(", ")}${e.length>t?`, +${e.length-t} more`:""}`,Jn=e=>e===1?"":"s";function Qr(e){if(e.error)return[`\u26A0 Couldn't check Document360 for portal changes (${e.error.slice(0,100)}) \u2014 proceeding; the agent will re-check.`];let t=[];return e.pulled.length&&t.push(`\u2713 Pulled ${e.pulled.length} portal edit${Jn(e.pulled.length)} into local: ${zr(e.pulled)}`),e.conflicts.length&&t.push(`\u26A0 ${e.conflicts.length} article${Jn(e.conflicts.length)} changed both locally and in the portal \u2014 left untouched (resolve: /pull <path>): ${zr(e.conflicts)}`),e.untrackedRemote.length&&t.push(`\u2139 ${e.untrackedRemote.length} new article${Jn(e.untrackedRemote.length)} in the portal aren't local yet \u2014 run /pull to bring them in: ${zr(e.untrackedRemote)}`),e.failed.length&&t.push(`\u26A0 ${e.failed.length} pull${Jn(e.failed.length)} failed \u2014 left for /pull.`),t}async function ja(e,t){let n=t?.cwd??process.cwd();if(!ap(n))return console.log(v("No d360-writer config here. Run /init first.")),{kind:"continue"};let o=Ne(n,t?.profileName);if(!o.ok)return console.log(v(o.reason)),{kind:"continue"};let{publish:r}=Kr(e);console.log(f("Reconciling with Document360 (pulling any portal changes)\u2026"));let s=await Jr({cwd:n,profileName:t?.profileName});for(let p of Qr(s))console.log(p.startsWith("\u2713")?A(p):p.startsWith("\u2139")?f(p):M(p));let c=_t(Nt(n));return console.log(f(c?`Catching up on ${c}\u2026`:"Checking for code changes the builder didn't hint\u2026")),{kind:"forward-to-agent",prompt:Xr({publish:r}),display:`/catch-up${r?" --publish":""}`}}W();import{spawn as pp}from"node:child_process";var ut="document360-writer",Qn=`npm i -g ${ut}@latest`;async function Zn(){let e=process.platform==="win32";return new Promise(t=>{try{let n=pp(`npm i -g ${ut}@latest`,{stdio:"ignore",shell:!0,detached:!e,windowsHide:!0});n.on("error",o=>t({ok:!1,output:String(o)})),n.on("close",o=>t({ok:o===0,output:""})),e||n.unref()}catch(n){t({ok:!1,output:String(n)})}})}async function Aa(){return console.log(f(`Updating ${ut}\u2026`)),(await Zn()).ok?console.log(A("\u2713 Updated. Exit (/exit) and relaunch d360-writer to apply.")):console.log(v(`Update failed \u2014 run manually: ${Qn}`)),{kind:"continue"}}W();at();import{existsSync as Zr,rmSync as fp}from"node:fs";import{basename as Ea,resolve as es}from"node:path";import{execFileSync as mp}from"node:child_process";import{input as hp}from"@inquirer/prompts";import{readProjectConfig as gp,devHintsGuidePath as wp}from"document360-engine";var yp=[".d360-writer.json",".d360-writer","d360-category-map.json",".d360-capture.json",".d360-capture-cache"],kp=new Set([".d360-writer.json","d360-category-map.json",".d360-capture.json",".d360-capture-cache"]),eo=e=>(e??"").replace(/\\/g,"/").replace(/\/+$/,""),Ia=e=>e===".d360-writer"||e.startsWith(".d360-writer/");function Na(e){let t=eo(e);return t===""||t.startsWith("..")||t.startsWith("/")||/^[a-zA-Z]:/.test(t)?!1:Ia(t)?!0:kp.has(t)}function ts(e){let t=null;try{t=gp(e)}catch{t=null}let n=new Set(yp);for(let o of[eo(t?.docsDir),eo(t?.captureDir),eo(t?.outputDir)])o&&Ia(o)&&n.add(o);return[...n].filter(o=>Na(o)&&Zr(es(e,o)))}function ns(e,t){let n=[],o=[];for(let r of t){if(!Na(r)){o.push({path:r,error:"refused \u2014 outside .d360-writer/ (protected)"});continue}try{fp(es(e,r),{recursive:!0,force:!0}),n.push(r)}catch(s){o.push({path:r,error:s.message})}}return{removed:n,failed:o}}function _a(e,t){try{return mp("git",["status","--porcelain","--",t],{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).split(`
|
|
248
|
-
`).filter(o=>o.trim()&&/\.md\s*$/.test(o)).length}catch{return 0}}function bp(e){return _a(e,".d360-writer/hints")}function xp(e){return _a(e,".d360-writer/messages")}function os(e,t){if(t.length===0)return["Nothing to reset \u2014 no d360-writer files found in this repo."];let n=bp(e),o=xp(e),r=Zr(es(e,"user-docs"));return["\u26A0 This permanently DELETES everything d360-writer created here:",...t.map(s=>` \u2022 ${s}`),"",...n>0?[`\u26A0 ${n} doc hint(s) under .d360-writer/hints/ are not committed \u2014 commit them first or they're gone.`]:[],...o>0?[`\u26A0 ${o} message(s) under .d360-writer/messages/ are not committed \u2014 commit them first or they're gone.`]:[],...r?["Note: a repo-root user-docs/ is NOT touched (only .d360-writer/ is removed)."]:[],"Undo = git: committed files are restorable; untracked ones (most screenshots) are gone.",`To confirm, type the repo name: ${Ea(e)}`]}async function Ma(e,t){let n=ts(t.cwd);for(let h of os(t.cwd,n))console.log(n.length===0?f(h):h);if(n.length===0)return{kind:"continue"};let o=Ea(t.cwd);if((await t.withPausedInput(()=>hp({message:`Type "${o}" to delete (anything else cancels):`}).catch(()=>""))).trim()!==o)return console.log(M("Reset cancelled \u2014 nothing deleted.")),{kind:"continue"};let s=Zr(wp(t.cwd)),{removed:c,failed:p}=ns(t.cwd,n);console.log(A(`\u2713 Reset complete \u2014 removed ${c.length} item${c.length===1?"":"s"}. The repo is back to its original state.`));for(let h of p)console.log(v(` \u2717 ${h.path}: ${h.error}`));if(s){for(let h of Ln())console.log(h);console.log(f("(Select and copy the prompt above to paste into your coding agent.)"))}return console.log(f("Set up d360-writer again with /init (then /login, /workspace).")),{kind:"continue"}}W();import{lintDocs as $p}from"document360-engine";function rs(e){if(e.length===0)return["\u2713 No
|
|
248
|
+
`).filter(o=>o.trim()&&/\.md\s*$/.test(o)).length}catch{return 0}}function bp(e){return _a(e,".d360-writer/hints")}function xp(e){return _a(e,".d360-writer/messages")}function os(e,t){if(t.length===0)return["Nothing to reset \u2014 no d360-writer files found in this repo."];let n=bp(e),o=xp(e),r=Zr(es(e,"user-docs"));return["\u26A0 This permanently DELETES everything d360-writer created here:",...t.map(s=>` \u2022 ${s}`),"",...n>0?[`\u26A0 ${n} doc hint(s) under .d360-writer/hints/ are not committed \u2014 commit them first or they're gone.`]:[],...o>0?[`\u26A0 ${o} message(s) under .d360-writer/messages/ are not committed \u2014 commit them first or they're gone.`]:[],...r?["Note: a repo-root user-docs/ is NOT touched (only .d360-writer/ is removed)."]:[],"Undo = git: committed files are restorable; untracked ones (most screenshots) are gone.",`To confirm, type the repo name: ${Ea(e)}`]}async function Ma(e,t){let n=ts(t.cwd);for(let h of os(t.cwd,n))console.log(n.length===0?f(h):h);if(n.length===0)return{kind:"continue"};let o=Ea(t.cwd);if((await t.withPausedInput(()=>hp({message:`Type "${o}" to delete (anything else cancels):`}).catch(()=>""))).trim()!==o)return console.log(M("Reset cancelled \u2014 nothing deleted.")),{kind:"continue"};let s=Zr(wp(t.cwd)),{removed:c,failed:p}=ns(t.cwd,n);console.log(A(`\u2713 Reset complete \u2014 removed ${c.length} item${c.length===1?"":"s"}. The repo is back to its original state.`));for(let h of p)console.log(v(` \u2717 ${h.path}: ${h.error}`));if(s){for(let h of Ln())console.log(h);console.log(f("(Select and copy the prompt above to paste into your coding agent.)"))}return console.log(f("Set up d360-writer again with /init (then /login, /workspace).")),{kind:"continue"}}W();import{lintDocs as $p}from"document360-engine";function rs(e){if(e.length===0)return["\u2713 No issues found \u2014 no leaked internals, unknown commands, or stale version facts in the docs."];let t=new Map;for(let o of e){let r=t.get(o.path)??[];r.push(o),t.set(o.path,r)}let n=[`\u26A0 ${e.length} doc issue${e.length===1?"":"s"} in ${t.size} article${t.size===1?"":"s"} (leaked internals / unknown commands / stale facts):`];for(let[o,r]of t){n.push(` ${o}`);for(let s of r)n.push(` L${s.line}: "${s.term}" \u2014 ${s.message}`)}return n}async function Oa(e,t){console.log(f("Linting the docs for leaked engine internals\u2026"));let n=$p({cwd:t.cwd}),o=rs(n);for(let r of o)console.log(n.length===0?A(r):M(r));return console.log(""),{kind:"continue"}}var La={help:Vo,"?":Vo,clear:li,exit:zo,quit:zo,init:Pi,mcp:Wn,publish:Ui,audit:nn,scope:Fi,pull:zi,convert:Ki,write:Zi,draft:ra,document:sa,resume:la,rename:ca,profile:da,model:ma,doctor:rn,workspace:ba,project:xa,"allow-prod":$a,login:va,logout:Ca,screenshot:Xn,"capture-setup":sn,devhints:hi,inbox:Da,"catch-up":ja,update:Aa,reset:Ma,lint:Oa};function Ua(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}at();W();var vp={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"},Fa=160,is=200,Ha=40;function we(e,t){let n=e.replace(/\s+/g," ").trim();return n.length<=t?n:n.slice(0,t-1)+"\u2026"}function Wa(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}: ${we(typeof r=="string"?r:JSON.stringify(r),Ha)}`);return t.length>4&&n.push("\u2026"),we(n.join(", "),Fa)}var Ye=e=>typeof e=="string"&&e?e:null,ss=e=>typeof e=="string"&&e.length>=8?e.slice(0,8):null;function Cp(e){let t=Ye(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 Pp(e,t){let n=(o,r)=>({title:`Document360: ${o}`,sep:" ",arg:r});switch(e){case"d360_create_article":{let o=Ye(t.title);if(!o)return null;let r=Cp(t.local_path);return n("Create article",`"${we(o,60)}"${r?` in ${r}`:""}`)}case"d360_update_article":{let o=Ye(t.title),r=ss(t.article_id);return n("Update article",o?`"${we(o,60)}"`:r?`id ${r}\u2026`:null)}case"d360_fork_article":return n("Fork article (new draft)",ss(t.article_id)?`id ${ss(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",Ye(t.name)?`"${we(Ye(t.name),60)}"`:null);case"d360_upload_drive_file":{let o=Ye(t.file_path);return n("Upload image",o?we(o.replace(/\\/g,"/").split("/").pop()??o,60):null)}case"d360_sync_status":return n("Check sync status",null);default:return null}}function to(e,t){if(e==="ToolSearch")return null;if(e.startsWith("mcp__")){let[,r="",...s]=e.split("__"),c=s.join("__");if(r==="document360"){let b=Pp(c,t);if(b)return b}let p=c.replace(/^d360_/,"").replace(/_/g," ");return{title:`${r==="document360"?"Document360":r.charAt(0).toUpperCase()+r.slice(1)}: ${p}`,sep:" ",arg:Wa(t)}}let n=vp[e],o=n?t[n]:void 0;return typeof o=="string"&&o?{title:e,sep:"",arg:we(o,Fa)}:{title:e,sep:"",arg:Wa(t)}}function Rp(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 Tp(e){if(!/^[[{]/.test(e))return null;let t;try{t=JSON.parse(e)}catch{return null}if(Array.isArray(t)){let n=t.map(Rp).filter(r=>r!==null),o=`${t.length} item${t.length===1?"":"s"}`;return n.length===0?[o]:[o,...n.map(r=>we(r,is))]}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}: ${we(String(r),Ha)}`);return n.length>0?[we(n.join(" \xB7 "),is)]:null}return null}function Sp(e){let t=Ye(e)?.replace(/\\/g,"/");if(!t)return null;let n=t.split("/").filter(Boolean);return n.length>1?n.slice(1).join("/"):t}function Dp(e,t,n){switch(e){case"d360_create_article":{let o=Sp(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=Ye(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 ${we(o[0],120)}`:""}`]}default:return null}}function no(e,t=4,n,o){let r=e.replace(/\r\n/g,`
|
|
249
249
|
`).trimEnd();if(!r)return{lines:["(no output)"],hidden:0};if(n?.startsWith("mcp__document360__")){let c=Dp(n.slice(18),o,r);if(c)return{lines:c,hidden:0}}let s=Tp(r)??r.split(`
|
|
250
250
|
`);return{lines:s.slice(0,t).map(c=>we(c,is)),hidden:Math.max(0,s.length-t)}}function oo(e,t,n,o="en"){return`${e.replace(/\/$/,"")}/${t}/document/v1/${o}/${n}`}function ro(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 so(e){try{let t=JSON.parse(e),o=(Array.isArray(t)?t[0]:t)?.url;return typeof o=="string"&&/^https?:\/\//.test(o)?o:null}catch{return null}}var Fp=/^mcp__document360__d360_(create_article|update_article|fork_article|publish_article)$/;function Hp(e,t,n,o){if(Fp.test(e))try{let r=Ga(o),s=typeof t.project_id=="string"&&t.project_id||r.project.projectId,c=ro(t,n),p=so(n);e.endsWith("publish_article")&&p&&console.log(N(` \u2B95 Live: ${p}`)),c&&s&&console.log(N(` \u2B95 Preview: ${oo(r.connection.portalUrl,s,c,r.project.languageCode??"en")}`))}catch{}}async function Va(e=process.cwd(),t="auto",n){let o=Ap(t);o.kind==="none"&&(console.error(""),console.error(v("ANTHROPIC_API_KEY is not set (required for --auth api).")),console.error(""),console.error(` ${N("export ANTHROPIC_API_KEY=sk-ant-...")} (macOS / Linux)`),console.error(` ${N('$env:ANTHROPIC_API_KEY="sk-ant-..."')} (PowerShell)`),console.error(""),console.error(`Get a key at ${N("https://console.anthropic.com/settings/keys")}`),console.error(`Or use your Claude subscription instead: ${N("d360-writer --auth subscription")}`),console.error(""),process.exit(2)),qp(e,n),o.kind==="subscription"&&(o.stored?console.log(f(" Using your Claude subscription (no API key set).")):console.log(f(" No API key or stored Claude Code login found \u2014 trying your Claude session anyway.")),console.log(""));let r=!1,s=as({cwd:e,profileName:n,allowProdWrites:r}),c={uuid:null,firstPrompt:null,titleFired:!1},p=jp({input:process.stdin,output:process.stdout}),h=[],b=null,x=!1;p.on("line",P=>{if(b){let C=b;b=null,C(P)}else h.push(P)}),p.on("close",()=>{if(x=!0,b){let P=b;b=null,P(null)}});function D(){return h.length>0?Promise.resolve(h.shift()):x?Promise.resolve(null):(process.stdout.write(N("> ")),new Promise(P=>{b=P}))}let y={cwd:e,profileName:n,allowProdWrites:()=>r,restartAgent:()=>{s.close(),s=as({cwd:e,profileName:n,allowProdWrites:r}),c={uuid:null,firstPrompt:null,titleFired:!1}},currentUuid:()=>c.uuid,setPendingName:P=>{c.pendingName=P},setModel:async P=>s.setModel(P),withPausedInput:async P=>{p.pause();try{return await P()}finally{p.resume()}}};try{for(;;){let P=await D();if(P===null)break;let C=P.trim();if(C){if(C.startsWith("/")){let I=Ua(C);if(!I)continue;let _=La[I.name];if(!_){console.log(v(`Unknown command: /${I.name}`)),console.log(f("Type /help for the list."));continue}let L=await _(I.args,y);if(L.kind==="exit")break;if(L.kind==="clear"){y.restartAgent();continue}if(L.kind==="allow-prod"){r=!0,y.restartAgent(),console.log(A("\u2713 Production writes authorized for this session.")),console.log("");continue}if(L.kind==="resume"){s.close(),s=as({cwd:e,resume:L.uuid,profileName:n,allowProdWrites:r});let Q=Ep(L.uuid);c={uuid:L.uuid,firstPrompt:Q?.firstPrompt??null,titleFired:!0},Ya(L.uuid),console.log(A(`\u2713 Resumed "${L.name}"`)),console.log("");continue}L.kind==="forward-to-agent"&&(c.firstPrompt||(c.firstPrompt=L.display??L.prompt),await Ba(s,L.prompt,o,c,e));continue}c.firstPrompt||(c.firstPrompt=C),await Ba(s,C,o,c,e)}}}finally{s.close(),p.close()}}function qp(e,t){console.log(""),console.log(Gt("document360-writer")),console.log(f(` cwd: ${e}`));let n=Op(e);if(console.log(f(` model: ${n.model??"auto (engine right-sizes per task)"}${n.model?` (${n.source})`:""}`)),console.log(Bp(e,t)),!Lp(e))console.log(M(" First run: /init (scaffolds config + prints the builder hand-off prompt) \u2192 /login, then ask me to write the docs."));else{try{Mn(e);for(let o of On(e))console.log(M(` ${o}`))}catch{}try{let o=_t(Nt(e));o&&console.log(M(` \u{1F4CB} ${o} from the repo's coding agent \u2014 run /catch-up.`))}catch{}}console.log(f(" Type a prompt, or /help for slash commands. /exit to quit.")),console.log("")}function Bp(e,t){try{let n=Ga(e,t),o=n.production?M(" \u26A0 PRODUCTION"):"",r=Wp(n.name);if(!r)return f(` Document360: profile "${n.name}"${o} \u2014 not logged in (d360-writer login)`);let s={...qa(r.idToken)??{},...qa(r.accessToken)??{}},c=s.email??s.preferred_username??"signed in";return Up(r)&&!r.refreshToken?M(` Document360: profile "${n.name}"${o} \u2014 session expired (d360-writer login)`):f(` Document360: ${c} \xB7 profile "${n.name}"${o}`)}catch(n){return f(` Document360: ${n.message.split(".")[0]}`)}}function Yp(){console.error(""),console.error(`Sign in with your Claude subscription: run ${N("claude")} once, then retry.`),console.error(` (No Claude Code? ${N("npm install -g @anthropic-ai/claude-code")})`),console.error(`Or set an API key: ${N("https://console.anthropic.com/settings/keys")}`)}function Gp(e,t,n){e.uuid=t;let o=new Date().toISOString(),r=e.pendingName;_p({uuid:t,name:r??Np(e.firstPrompt??"session"),renamed:!!r,titled:!1,cwd:n,firstPrompt:e.firstPrompt??"",createdAt:o,updatedAt:o}),e.pendingName=null}function Vp(e,t){e.titleFired=!0;let n=e.uuid,o=e.firstPrompt;!n||!o||Mp(o,t).then(r=>{r&&Ip(n,r)}).catch(()=>{})}async function Ba(e,t,n,o,r){let s=new Map;for await(let c of e.send(t))zp(c,o,r,n,s)}function zp(e,t,n,o,r){switch(e.type){case"session":t.uuid||Gp(t,e.sessionId,n);break;case"text":process.stdout.write(e.delta);break;case"tool":{let s=to(e.name,e.input);s&&(process.stdout.write(`
|
|
251
251
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document360-writer",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.40",
|
|
4
4
|
"description": "Standalone documentation agent CLI. Reads your code, writes your docs. Specialized for Document360 publishing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@inquirer/prompts": "^8.4.3",
|
|
35
35
|
"commander": "^14.0.3",
|
|
36
36
|
"diff": "^8.0.4",
|
|
37
|
-
"document360-engine": "^0.2.
|
|
37
|
+
"document360-engine": "^0.2.78",
|
|
38
38
|
"ink": "^5.2.1",
|
|
39
39
|
"picocolors": "^1.1.1",
|
|
40
40
|
"react": "^18.3.1",
|