austere-axi 0.5.1 → 0.5.2
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/README.md +3 -1
- package/dist/austere.js +2 -2
- package/dist/catalog.json +1 -1
- package/dist/cli.mjs +172 -38
- package/dist/packs/mermaid/catalog.json +2 -2
- package/dist/packs/mermaid/pack.js +1 -1
- package/dist/packs/shadcn/catalog.json +2 -2
- package/dist/packs/shadcn/pack.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -151,8 +151,10 @@ agent edits statements ◄── austere-axi poll plan.html ◄─┘ (long-pol
|
|
|
151
151
|
|
|
152
152
|
## CLI
|
|
153
153
|
|
|
154
|
+
Usage errors (unknown command or flag, missing argument) exit 2 before anything runs; failures exit 1. `<command> --help` prints that command's flags and an example.
|
|
155
|
+
|
|
154
156
|
```
|
|
155
|
-
austere-axi sessions +
|
|
157
|
+
austere-axi sessions + command list
|
|
156
158
|
austere-axi <file> validate + open a review [--no-open] [--reopen]
|
|
157
159
|
austere-axi poll <file> long-poll for feedback [--cursor n] [--agent-reply "..."] [--after n] [--takeover]
|
|
158
160
|
austere-axi reply <file> post a reply without polling [--cursor n]
|
package/dist/austere.js
CHANGED
|
@@ -1607,11 +1607,11 @@ dataLane = Group("DATA STORES WITH A HEADING LONGER THAN THE COLUMN IS WIDE", [c
|
|
|
1607
1607
|
<button type="button" data-act="queue" class="primary">Queue</button>
|
|
1608
1608
|
</span>
|
|
1609
1609
|
</div>
|
|
1610
|
-
</div>`,document.body.appendChild(r);let n=r.querySelector(".austere-hover"),o=r.querySelector(".austere-hover-label"),i=r.querySelector(".austere-selbtn"),l=r.querySelector(".austere-pop"),s=r.querySelector(".austere-pop-path"),u=r.querySelector(".austere-pop-quote"),d=r.querySelector("textarea"),p=null,f=null,m=0,x=null,v=Y=>!!Y?.closest?.(`[${S9}]`),w=Y=>Y?.closest?.("[data-oui-id]")||null;function b(Y,de,se=4){Y.style.left=`${de.left-se}px`,Y.style.top=`${de.top-se}px`,Y.style.width=`${de.width+se*2}px`,Y.style.height=`${de.height+se*2}px`}function k(Y){if(!Y){n.hidden=!0;return}b(n,SX(Y)),o.textContent=`${Y.getAttribute("data-oui-id")} \xB7 ${Y.getAttribute("data-oui-c")}`,n.hidden=!1}function I(Y){a!=="annotate"||!l.hidden||(x=Y.target,!m&&(m=requestAnimationFrame(()=>{m=0,!v(x)&&k(w(x))})))}function L(){let Y=window.getSelection();return!!Y&&!Y.isCollapsed&&Y.toString().trim().length>0}function M(Y){if(a!=="annotate"||v(Y.target))return;if(!l.hidden){Y.preventDefault(),Y.stopPropagation();return}if(L()||!Y.altKey&&Y.target.closest(t$a))return;let de=w(Y.target);de&&(Y.preventDefault(),Y.stopPropagation(),T({target:de,el:Y.target,point:{x:Y.clientX,y:Y.clientY}}))}function _(){if(a!=="annotate"||!l.hidden)return;let Y=window.getSelection();if(!Y||Y.isCollapsed||!Y.rangeCount){i.hidden=!0,f=null;return}let de=Y.toString().trim(),se=Y.getRangeAt(0),H=se.commonAncestorContainer;H.nodeType!==1&&(H=H.parentElement);let ee=w(H);if(!de||!ee||v(H)){i.hidden=!0,f=null;return}let oe=se.getBoundingClientRect();f={target:ee,el:H,selection:vv(de,600),point:{x:oe.left,y:oe.bottom}},i.hidden=!1;let he=i.offsetWidth||140;i.style.left=`${Math.max(8,Math.min(window.innerWidth-he-8,oe.left+oe.width/2-he/2))}px`,i.style.top=`${Math.max(8,Math.min(window.innerHeight-40,oe.bottom+8))}px`}let A=0;function D(){clearTimeout(A),A=setTimeout(_,120)}i.addEventListener("mousedown",Y=>Y.preventDefault()),i.addEventListener("click",Y=>{Y.preventDefault(),Y.stopPropagation(),f&&T(f),i.hidden=!0});function E(){s.textContent="",p.path.forEach((Y,de)=>{let se=document.createElement("button");if(se.type="button",se.className="austere-chip"+(Y.id===p.targetId?" active":""),se.textContent=Y.id,se.title=Y.component,se.addEventListener("click",()=>{p.targetId=Y.id,p.component=Y.component,E(),d.focus()}),s.appendChild(se),de<p.path.length-1){let H=document.createElement("span");H.className="austere-chip-sep",H.textContent="\u203A",s.appendChild(H)}})}function T({target:Y,el:de,selection:se,point:H}){let ee=a$a(Y),oe=r$a(Y,de),he=IEt(Y,de),_e;se||(_e=vv((he||de).innerText||(he||de).textContent,200)||void 0,he&&_e===oe?.part&&(_e=void 0)),p={targetId:Y.getAttribute("data-oui-id"),component:Y.getAttribute("data-oui-c"),path:ee,selection:se||void 0,excerpt:_e,detail:oe},E();let Me=se||_e||oe?.part||"";u.textContent=vv(Me,220),u.hidden=!Me,d.value="",n.hidden=!0,i.hidden=!0,k(Y),n.classList.add("locked"),l.hidden=!1,O(H),d.focus()}function O(Y){if(window.innerWidth<640){l.classList.add("sheet"),l.style.left=l.style.top="";return}l.classList.remove("sheet");let de=l.offsetWidth||360,se=l.offsetHeight||200,H=Y.x+12,ee=Y.y+12;H+de>window.innerWidth-8&&(H=Math.max(8,Y.x-de-12)),ee+se>window.innerHeight-8&&(ee=Math.max(8,Y.y-se-12)),l.style.left=`${H}px`,l.style.top=`${ee}px`}function $(){l.hidden=!0,n.classList.remove("locked"),n.hidden=!0,p=null}function P(){let Y=d.value.trim();if(!p)return;if(!Y&&!p.selection){d.focus(),d.classList.add("shake"),setTimeout(()=>d.classList.remove("shake"),400);return}let de={kind:"annotation",target:p.targetId,component:p.component,path:p.path.map(H=>H.id),note:Y};p.selection&&(de.selection=p.selection),p.excerpt&&!p.selection&&(de.excerpt=p.excerpt),p.detail&&p.targetId===p.path[p.path.length-1].id&&(de.detail=p.detail),e({type:"annotate",item:de});let se=p.targetId;$(),window.getSelection()?.removeAllRanges(),re([se],"queued")}l.addEventListener("click",Y=>{let de=Y.target.closest("[data-act]")?.getAttribute("data-act");de==="cancel"&&$(),de==="queue"&&P()}),d.addEventListener("keydown",Y=>{Y.key==="Enter"&&!Y.shiftKey&&!Y.isComposing?(Y.preventDefault(),P()):Y.key==="Escape"&&(Y.preventDefault(),d.value.trim()||$())}),document.addEventListener("mousemove",I,{passive:!0}),document.addEventListener("click",M,!0),document.addEventListener("mouseup",D),document.addEventListener("keyup",Y=>{(Y.shiftKey||Y.key.startsWith("Arrow"))&&D()}),document.addEventListener("selectionchange",()=>{"ontouchstart"in window&&D()}),document.addEventListener("keydown",Y=>{(Y.metaKey||Y.ctrlKey)&&(Y.key==="i"||Y.key==="I")&&(Y.preventDefault(),e({type:"toggle-mode"}))}),window.addEventListener("scroll",()=>{l.hidden&&(n.hidden=!0,i.hidden=!0)},{passive:!0}),document.addEventListener("mouseleave",()=>{l.hidden&&(n.hidden=!0)});function q(Y,de,se,H=new Set){if(H.has(Y))return[];H.add(Y);let ee=document.querySelectorAll(`[data-oui-id="${CSS.escape(Y)}"]`);return ee.length?Array.from(ee):!de||!se?[]:se(de,Y).flatMap(oe=>q(oe,de,se,H))}function V(Y,de,se){let H=new Set;for(let ee of Y)for(let oe of q(ee,de,se))H.add(oe);return Array.from(H).filter(ee=>!Array.from(H).some(oe=>oe!==ee&&oe.contains(ee)))}function Z(Y,de){let se=document.createElement("div");return se.setAttribute(S9,""),se.className=de,se.style.left=`${Y.left+window.scrollX-4}px`,se.style.top=`${Y.top+window.scrollY-4}px`,se.style.width=`${Y.width+8}px`,se.style.height=`${Y.height+8}px`,se}function X(Y){if(getComputedStyle(Y).display!=="contents")return Y.getBoundingClientRect();let[de,se,H,ee]=[1/0,1/0,-1/0,-1/0],oe=_e=>{!_e.width&&!_e.height||([de,se,H,ee]=[Math.min(de,_e.left),Math.min(se,_e.top),Math.max(H,_e.right),Math.max(ee,_e.bottom)])},he=_e=>{for(let Me of _e.childNodes)if(Me.nodeType===Node.ELEMENT_NODE)getComputedStyle(Me).display==="contents"?he(Me):oe(Me.getBoundingClientRect());else if(Me.nodeType===Node.TEXT_NODE&&Me.textContent.trim()){let rt=document.createRange();rt.selectNodeContents(Me),oe(rt.getBoundingClientRect())}};return he(Y),{left:de,top:se,right:H,bottom:ee}}function ae(Y){let{left:de,top:se,right:H,bottom:ee}=X(Y);for(let oe=Y.parentElement;oe&&oe!==document.body;oe=oe.parentElement){let he=getComputedStyle(oe),_e=he.overflowX!=="visible",Me=he.overflowY!=="visible";if(!_e&&!Me||he.display==="contents")continue;let rt=oe.getBoundingClientRect();_e&&([de,H]=[Math.max(de,rt.left),Math.min(H,rt.right)]),Me&&([se,ee]=[Math.max(se,rt.top),Math.min(ee,rt.bottom)])}return H>de&&ee>se?{left:de,top:se,width:H-de,height:ee-se}:null}function re(Y,de="changed",se,H){let ee=V(Y,se,H);for(let oe of ee){let he=ae(oe);if(!he)continue;let _e=Z(he,`austere-flash ${de}`);document.body.appendChild(_e),setTimeout(()=>_e.remove(),2400)}return ee}function F(Y,de,se){let H=q(Y,de,se);if(!H.length)return!1;let ee=SX(H[0]),oe=ee.top+window.scrollY-Math.max(24,(window.innerHeight-ee.height)/3);return window.scrollTo({top:Math.max(0,oe),behavior:"smooth"}),setTimeout(()=>re([Y],"changed",de,se),350),!0}let le=document.createElement("div");le.setAttribute(S9,""),r.appendChild(le);let ge=null,U=0;function Oe(){U=0;let[Y,de]=ge&&t?t():[],se=[],H=[];for(let ee of ge?V(ge,Y,de):[]){let oe=ae(ee);oe&&(se.push(ee),H.push(oe))}return le.replaceChildren(...H.map(ee=>Z(ee,"austere-mark"))),se}let Be=()=>{ge&&!U&&(U=requestAnimationFrame(Oe))};window.addEventListener("resize",Be,{passive:!0}),new ResizeObserver(Be).observe(document.body),new MutationObserver(Y=>{Y.some(de=>!v(de.target.nodeType===1?de.target:de.target.parentElement))&&Be()}).observe(document.body,{childList:!0,subtree:!0,characterData:!0,attributes:!0,attributeFilter:["class","style","hidden","open"]}),document.addEventListener("scroll",Y=>{Y.target!==document&&Be()},{capture:!0,passive:!0});function Fe(Y,de=!1){ge=Y.length?Y:null;let se=Oe();if(de&&se.length){let H=se.map(SX);if(!H.some(ee=>ee.bottom>0&&ee.top<window.innerHeight)){let ee=H[0],oe=ee.top+window.scrollY-Math.max(24,(window.innerHeight-ee.height)/3);window.scrollTo({top:Math.max(0,oe),behavior:"smooth"})}}return se.length}return{setMode(Y){a=Y==="annotate"?"annotate":"explore",document.documentElement.classList.toggle("austere-annotating",a==="annotate"),a!=="annotate"&&($(),i.hidden=!0,n.hidden=!0)},flash:re,reveal:F,highlight:Fe}}var LEt={mermaid:{name:"@austere-axi/pack-mermaid",version:"0.5.1",components:["Mermaid"]},shadcn:{name:"@austere-axi/pack-shadcn",version:"0.5.1",components:["Progress","Avatar","AvatarGroup","Tooltip","HoverCard","Breadcrumb","BreadcrumbItem","Kbd","Skeleton","Calendar","Timeline","TimelineItem"]}};function n$a(e){let t=e.lastIndexOf("@");return t<=0?{name:e,version:""}:{name:e.slice(0,t),version:e.slice(t+1)}}var o$a=/^(@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/,i$a=/^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/;function _Et(e){let t=[];for(let a of String(e||"").split(",")){let[r,n]=a.trim().split(/\s+/);if(!r)continue;let{name:o,version:i}=n$a(r);!o$a.test(o)||!i$a.test(i)||t.some(l=>l.name===o)||t.push(n&&/^sha(256|384|512)-[A-Za-z0-9+/=]+$/.test(n)?{name:o,version:i,integrity:n}:{name:o,version:i})}return t}var MEt="https://cdn.jsdelivr.net/npm";function CEt(e=document){let t=e.querySelector('meta[name="austere-packs"]');return t?_Et(t.getAttribute("content")||""):[]}function AEt(e,t){let a=[...t];for(let[r,n]of Object.entries(LEt))a.some(o=>o.name===n.name)||n.components.some(o=>new RegExp(`\\b${o}\\s*\\(`).test(e))&&a.push({name:n.name,version:n.version,bundled:r});return a}function LX(){return/\/__austere\/$/.test(I2)}function l$a(e){if(e.bundled)return{src:B4(`packs/${e.bundled}/pack.js`)||`${MEt}/austere-axi@${e.version}/dist/packs/${e.bundled}/pack.js`};if(LX()){let t=e.integrity?`?integrity=${encodeURIComponent(e.integrity)}`:"";return{src:`${I2}installed-packs/${encodeURIComponent(`${e.name}@${e.version}`)}/pack.js${t}`}}return{src:`${MEt}/${e.name}@${e.version}/dist/pack.js`,integrity:e.integrity}}function s$a(e,t){return new Promise((a,r)=>{let n=document.createElement("script");n.src=e,n.async=!0,t&&(n.integrity=t,n.crossOrigin="anonymous"),n.onload=()=>a(),n.onerror=()=>r(new Error(`could not load ${e}`)),document.head.appendChild(n)})}async function NEt(e,{onError:t}={}){let a=e.filter(r=>!ys().some(n=>n.name===r.name));return await Promise.all(a.map(r=>{let{src:n,integrity:o}=l$a(r);return s$a(n,o).then(()=>{ys().some(i=>i.name===r.name)||t?.(r,new Error(`${n} loaded but did not register pack ${r.name}`))},i=>t?.(r,i))})),ys()}function TEt(e){for(let t of e){if(!t.css)continue;let a=`austere-pack-css-${t.name.replace(/[^a-z0-9]/gi,"-")}`;if(document.getElementById(a))continue;let r=document.createElement("style");r.id=a,r.textContent=t.css,document.head.appendChild(r)}}var c$a=/[A-Za-z_$]/;function u$a(e){let t=[],a=String(e??""),r=0,n=1,o=a.length;for(;r<o;){let i=a[r];if(i===`
|
|
1610
|
+
</div>`,document.body.appendChild(r);let n=r.querySelector(".austere-hover"),o=r.querySelector(".austere-hover-label"),i=r.querySelector(".austere-selbtn"),l=r.querySelector(".austere-pop"),s=r.querySelector(".austere-pop-path"),u=r.querySelector(".austere-pop-quote"),d=r.querySelector("textarea"),p=null,f=null,m=0,x=null,v=Y=>!!Y?.closest?.(`[${S9}]`),w=Y=>Y?.closest?.("[data-oui-id]")||null;function b(Y,de,se=4){Y.style.left=`${de.left-se}px`,Y.style.top=`${de.top-se}px`,Y.style.width=`${de.width+se*2}px`,Y.style.height=`${de.height+se*2}px`}function k(Y){if(!Y){n.hidden=!0;return}b(n,SX(Y)),o.textContent=`${Y.getAttribute("data-oui-id")} \xB7 ${Y.getAttribute("data-oui-c")}`,n.hidden=!1}function I(Y){a!=="annotate"||!l.hidden||(x=Y.target,!m&&(m=requestAnimationFrame(()=>{m=0,!v(x)&&k(w(x))})))}function L(){let Y=window.getSelection();return!!Y&&!Y.isCollapsed&&Y.toString().trim().length>0}function M(Y){if(a!=="annotate"||v(Y.target))return;if(!l.hidden){Y.preventDefault(),Y.stopPropagation();return}if(L()||!Y.altKey&&Y.target.closest(t$a))return;let de=w(Y.target);de&&(Y.preventDefault(),Y.stopPropagation(),T({target:de,el:Y.target,point:{x:Y.clientX,y:Y.clientY}}))}function _(){if(a!=="annotate"||!l.hidden)return;let Y=window.getSelection();if(!Y||Y.isCollapsed||!Y.rangeCount){i.hidden=!0,f=null;return}let de=Y.toString().trim(),se=Y.getRangeAt(0),H=se.commonAncestorContainer;H.nodeType!==1&&(H=H.parentElement);let ee=w(H);if(!de||!ee||v(H)){i.hidden=!0,f=null;return}let oe=se.getBoundingClientRect();f={target:ee,el:H,selection:vv(de,600),point:{x:oe.left,y:oe.bottom}},i.hidden=!1;let he=i.offsetWidth||140;i.style.left=`${Math.max(8,Math.min(window.innerWidth-he-8,oe.left+oe.width/2-he/2))}px`,i.style.top=`${Math.max(8,Math.min(window.innerHeight-40,oe.bottom+8))}px`}let A=0;function D(){clearTimeout(A),A=setTimeout(_,120)}i.addEventListener("mousedown",Y=>Y.preventDefault()),i.addEventListener("click",Y=>{Y.preventDefault(),Y.stopPropagation(),f&&T(f),i.hidden=!0});function E(){s.textContent="",p.path.forEach((Y,de)=>{let se=document.createElement("button");if(se.type="button",se.className="austere-chip"+(Y.id===p.targetId?" active":""),se.textContent=Y.id,se.title=Y.component,se.addEventListener("click",()=>{p.targetId=Y.id,p.component=Y.component,E(),d.focus()}),s.appendChild(se),de<p.path.length-1){let H=document.createElement("span");H.className="austere-chip-sep",H.textContent="\u203A",s.appendChild(H)}})}function T({target:Y,el:de,selection:se,point:H}){let ee=a$a(Y),oe=r$a(Y,de),he=IEt(Y,de),_e;se||(_e=vv((he||de).innerText||(he||de).textContent,200)||void 0,he&&_e===oe?.part&&(_e=void 0)),p={targetId:Y.getAttribute("data-oui-id"),component:Y.getAttribute("data-oui-c"),path:ee,selection:se||void 0,excerpt:_e,detail:oe},E();let Me=se||_e||oe?.part||"";u.textContent=vv(Me,220),u.hidden=!Me,d.value="",n.hidden=!0,i.hidden=!0,k(Y),n.classList.add("locked"),l.hidden=!1,O(H),d.focus()}function O(Y){if(window.innerWidth<640){l.classList.add("sheet"),l.style.left=l.style.top="";return}l.classList.remove("sheet");let de=l.offsetWidth||360,se=l.offsetHeight||200,H=Y.x+12,ee=Y.y+12;H+de>window.innerWidth-8&&(H=Math.max(8,Y.x-de-12)),ee+se>window.innerHeight-8&&(ee=Math.max(8,Y.y-se-12)),l.style.left=`${H}px`,l.style.top=`${ee}px`}function $(){l.hidden=!0,n.classList.remove("locked"),n.hidden=!0,p=null}function P(){let Y=d.value.trim();if(!p)return;if(!Y&&!p.selection){d.focus(),d.classList.add("shake"),setTimeout(()=>d.classList.remove("shake"),400);return}let de={kind:"annotation",target:p.targetId,component:p.component,path:p.path.map(H=>H.id),note:Y};p.selection&&(de.selection=p.selection),p.excerpt&&!p.selection&&(de.excerpt=p.excerpt),p.detail&&p.targetId===p.path[p.path.length-1].id&&(de.detail=p.detail),e({type:"annotate",item:de});let se=p.targetId;$(),window.getSelection()?.removeAllRanges(),re([se],"queued")}l.addEventListener("click",Y=>{let de=Y.target.closest("[data-act]")?.getAttribute("data-act");de==="cancel"&&$(),de==="queue"&&P()}),d.addEventListener("keydown",Y=>{Y.key==="Enter"&&!Y.shiftKey&&!Y.isComposing?(Y.preventDefault(),P()):Y.key==="Escape"&&(Y.preventDefault(),d.value.trim()||$())}),document.addEventListener("mousemove",I,{passive:!0}),document.addEventListener("click",M,!0),document.addEventListener("mouseup",D),document.addEventListener("keyup",Y=>{(Y.shiftKey||Y.key.startsWith("Arrow"))&&D()}),document.addEventListener("selectionchange",()=>{"ontouchstart"in window&&D()}),document.addEventListener("keydown",Y=>{(Y.metaKey||Y.ctrlKey)&&(Y.key==="i"||Y.key==="I")&&(Y.preventDefault(),e({type:"toggle-mode"}))}),window.addEventListener("scroll",()=>{l.hidden&&(n.hidden=!0,i.hidden=!0)},{passive:!0}),document.addEventListener("mouseleave",()=>{l.hidden&&(n.hidden=!0)});function q(Y,de,se,H=new Set){if(H.has(Y))return[];H.add(Y);let ee=document.querySelectorAll(`[data-oui-id="${CSS.escape(Y)}"]`);return ee.length?Array.from(ee):!de||!se?[]:se(de,Y).flatMap(oe=>q(oe,de,se,H))}function V(Y,de,se){let H=new Set;for(let ee of Y)for(let oe of q(ee,de,se))H.add(oe);return Array.from(H).filter(ee=>!Array.from(H).some(oe=>oe!==ee&&oe.contains(ee)))}function Z(Y,de){let se=document.createElement("div");return se.setAttribute(S9,""),se.className=de,se.style.left=`${Y.left+window.scrollX-4}px`,se.style.top=`${Y.top+window.scrollY-4}px`,se.style.width=`${Y.width+8}px`,se.style.height=`${Y.height+8}px`,se}function X(Y){if(getComputedStyle(Y).display!=="contents")return Y.getBoundingClientRect();let[de,se,H,ee]=[1/0,1/0,-1/0,-1/0],oe=_e=>{!_e.width&&!_e.height||([de,se,H,ee]=[Math.min(de,_e.left),Math.min(se,_e.top),Math.max(H,_e.right),Math.max(ee,_e.bottom)])},he=_e=>{for(let Me of _e.childNodes)if(Me.nodeType===Node.ELEMENT_NODE)getComputedStyle(Me).display==="contents"?he(Me):oe(Me.getBoundingClientRect());else if(Me.nodeType===Node.TEXT_NODE&&Me.textContent.trim()){let rt=document.createRange();rt.selectNodeContents(Me),oe(rt.getBoundingClientRect())}};return he(Y),{left:de,top:se,right:H,bottom:ee}}function ae(Y){let{left:de,top:se,right:H,bottom:ee}=X(Y);for(let oe=Y.parentElement;oe&&oe!==document.body;oe=oe.parentElement){let he=getComputedStyle(oe),_e=he.overflowX!=="visible",Me=he.overflowY!=="visible";if(!_e&&!Me||he.display==="contents")continue;let rt=oe.getBoundingClientRect();_e&&([de,H]=[Math.max(de,rt.left),Math.min(H,rt.right)]),Me&&([se,ee]=[Math.max(se,rt.top),Math.min(ee,rt.bottom)])}return H>de&&ee>se?{left:de,top:se,width:H-de,height:ee-se}:null}function re(Y,de="changed",se,H){let ee=V(Y,se,H);for(let oe of ee){let he=ae(oe);if(!he)continue;let _e=Z(he,`austere-flash ${de}`);document.body.appendChild(_e),setTimeout(()=>_e.remove(),2400)}return ee}function F(Y,de,se){let H=q(Y,de,se);if(!H.length)return!1;let ee=SX(H[0]),oe=ee.top+window.scrollY-Math.max(24,(window.innerHeight-ee.height)/3);return window.scrollTo({top:Math.max(0,oe),behavior:"smooth"}),setTimeout(()=>re([Y],"changed",de,se),350),!0}let le=document.createElement("div");le.setAttribute(S9,""),r.appendChild(le);let ge=null,U=0;function Oe(){U=0;let[Y,de]=ge&&t?t():[],se=[],H=[];for(let ee of ge?V(ge,Y,de):[]){let oe=ae(ee);oe&&(se.push(ee),H.push(oe))}return le.replaceChildren(...H.map(ee=>Z(ee,"austere-mark"))),se}let Be=()=>{ge&&!U&&(U=requestAnimationFrame(Oe))};window.addEventListener("resize",Be,{passive:!0}),new ResizeObserver(Be).observe(document.body),new MutationObserver(Y=>{Y.some(de=>!v(de.target.nodeType===1?de.target:de.target.parentElement))&&Be()}).observe(document.body,{childList:!0,subtree:!0,characterData:!0,attributes:!0,attributeFilter:["class","style","hidden","open"]}),document.addEventListener("scroll",Y=>{Y.target!==document&&Be()},{capture:!0,passive:!0});function Fe(Y,de=!1){ge=Y.length?Y:null;let se=Oe();if(de&&se.length){let H=se.map(SX);if(!H.some(ee=>ee.bottom>0&&ee.top<window.innerHeight)){let ee=H[0],oe=ee.top+window.scrollY-Math.max(24,(window.innerHeight-ee.height)/3);window.scrollTo({top:Math.max(0,oe),behavior:"smooth"})}}return se.length}return{setMode(Y){a=Y==="annotate"?"annotate":"explore",document.documentElement.classList.toggle("austere-annotating",a==="annotate"),a!=="annotate"&&($(),i.hidden=!0,n.hidden=!0)},flash:re,reveal:F,highlight:Fe}}var LEt={mermaid:{name:"@austere-axi/pack-mermaid",version:"0.5.2",components:["Mermaid"]},shadcn:{name:"@austere-axi/pack-shadcn",version:"0.5.2",components:["Progress","Avatar","AvatarGroup","Tooltip","HoverCard","Breadcrumb","BreadcrumbItem","Kbd","Skeleton","Calendar","Timeline","TimelineItem"]}};function n$a(e){let t=e.lastIndexOf("@");return t<=0?{name:e,version:""}:{name:e.slice(0,t),version:e.slice(t+1)}}var o$a=/^(@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/,i$a=/^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/;function _Et(e){let t=[];for(let a of String(e||"").split(",")){let[r,n]=a.trim().split(/\s+/);if(!r)continue;let{name:o,version:i}=n$a(r);!o$a.test(o)||!i$a.test(i)||t.some(l=>l.name===o)||t.push(n&&/^sha(256|384|512)-[A-Za-z0-9+/=]+$/.test(n)?{name:o,version:i,integrity:n}:{name:o,version:i})}return t}var MEt="https://cdn.jsdelivr.net/npm";function CEt(e=document){let t=e.querySelector('meta[name="austere-packs"]');return t?_Et(t.getAttribute("content")||""):[]}function AEt(e,t){let a=[...t];for(let[r,n]of Object.entries(LEt))a.some(o=>o.name===n.name)||n.components.some(o=>new RegExp(`\\b${o}\\s*\\(`).test(e))&&a.push({name:n.name,version:n.version,bundled:r});return a}function LX(){return/\/__austere\/$/.test(I2)}function l$a(e){if(e.bundled)return{src:B4(`packs/${e.bundled}/pack.js`)||`${MEt}/austere-axi@${e.version}/dist/packs/${e.bundled}/pack.js`};if(LX()){let t=e.integrity?`?integrity=${encodeURIComponent(e.integrity)}`:"";return{src:`${I2}installed-packs/${encodeURIComponent(`${e.name}@${e.version}`)}/pack.js${t}`}}return{src:`${MEt}/${e.name}@${e.version}/dist/pack.js`,integrity:e.integrity}}function s$a(e,t){return new Promise((a,r)=>{let n=document.createElement("script");n.src=e,n.async=!0,t&&(n.integrity=t,n.crossOrigin="anonymous"),n.onload=()=>a(),n.onerror=()=>r(new Error(`could not load ${e}`)),document.head.appendChild(n)})}async function NEt(e,{onError:t}={}){let a=e.filter(r=>!ys().some(n=>n.name===r.name));return await Promise.all(a.map(r=>{let{src:n,integrity:o}=l$a(r);return s$a(n,o).then(()=>{ys().some(i=>i.name===r.name)||t?.(r,new Error(`${n} loaded but did not register pack ${r.name}`))},i=>t?.(r,i))})),ys()}function TEt(e){for(let t of e){if(!t.css)continue;let a=`austere-pack-css-${t.name.replace(/[^a-z0-9]/gi,"-")}`;if(document.getElementById(a))continue;let r=document.createElement("style");r.id=a,r.textContent=t.css,document.head.appendChild(r)}}var c$a=/[A-Za-z_$]/;function u$a(e){let t=[],a=String(e??""),r=0,n=1,o=a.length;for(;r<o;){let i=a[r];if(i===`
|
|
1611
1611
|
`){n++,r++;continue}if(i===" "||i===" "||i==="\r"){r++;continue}if(i==="#"||i==="/"&&a[r+1]==="/"){for(;r<o&&a[r]!==`
|
|
1612
1612
|
`;)r++;continue}let l=r,s=n,u=0,d=null,p=!1;for(;r<o;){let x=a[r];if(d){p?p=!1:x==="\\"?p=!0:x===d&&(d=null),x===`
|
|
1613
1613
|
`&&n++,r++;continue}if(x==='"'||x==="'"){d=x,r++;continue}if(x==="#"||x==="/"&&a[r+1]==="/"){for(;r<o&&a[r]!==`
|
|
1614
1614
|
`;)r++;continue}if(x==="("||x==="["||x==="{")u++;else if(x===")"||x==="]"||x==="}")u=Math.max(0,u-1);else if(x===`
|
|
1615
|
-
`){if(u===0&&!d$a(a,r+1))break;n++}r++}let f=a.slice(l,r).replace(/\s+$/,""),m=/^\s*([A-Za-z_$][\w$]*)\s*=/.exec(f);m&&c$a.test(m[1][0])&&t.push({id:m[1],text:f,line:s,endLine:n})}return t}function d$a(e,t){let a=t;for(;a<e.length&&(e[a]===" "||e[a]===" ");)a++;return e[a]==="?"||e[a]===":"}function eh(e){let t=new Map;for(let a of u$a(e))t.set(a.id,a);return t}function REt(e,t){let a=eh(e),r=eh(t),n=[];for(let[o,i]of r){let l=a.get(o);(!l||zEt(l.text)!==zEt(i.text))&&n.push(o)}return n}function L9(e,t){let a=new RegExp(`(^|[^\\w$])${f$a(t)}(?![\\w$])`),r=[];for(let[n,o]of e){if(n===t)continue;let i=o.text.slice(o.text.indexOf("=")+1);a.test(p$a(i))&&r.push(n)}return r}function p$a(e){return e.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/gs,'""')}function zEt(e){return e.replace(/\s+/g," ").trim()}function f$a(e){return e.replace(/[$()*+.?[\\\]^{|}]/g,"\\$&")}var kv=ne(It(),1),CX="0.5.
|
|
1615
|
+
`){if(u===0&&!d$a(a,r+1))break;n++}r++}let f=a.slice(l,r).replace(/\s+$/,""),m=/^\s*([A-Za-z_$][\w$]*)\s*=/.exec(f);m&&c$a.test(m[1][0])&&t.push({id:m[1],text:f,line:s,endLine:n})}return t}function d$a(e,t){let a=t;for(;a<e.length&&(e[a]===" "||e[a]===" ");)a++;return e[a]==="?"||e[a]===":"}function eh(e){let t=new Map;for(let a of u$a(e))t.set(a.id,a);return t}function REt(e,t){let a=eh(e),r=eh(t),n=[];for(let[o,i]of r){let l=a.get(o);(!l||zEt(l.text)!==zEt(i.text))&&n.push(o)}return n}function L9(e,t){let a=new RegExp(`(^|[^\\w$])${f$a(t)}(?![\\w$])`),r=[];for(let[n,o]of e){if(n===t)continue;let i=o.text.slice(o.text.indexOf("=")+1);a.test(p$a(i))&&r.push(n)}return r}function p$a(e){return e.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/gs,'""')}function zEt(e){return e.replace(/\s+/g," ").trim()}function f$a(e){return e.replace(/[$()*+.?[\\\]^{|}]/g,"\\$&")}var kv=ne(It(),1),CX="0.5.2",m$a='script[type="text/openui"], script[type="text/openui-lang"]';function h$a(){if(document.getElementById("austere-styles"))return;let e=document.createElement("style");if(e.id="austere-styles",e.textContent=[Coe,Loe,_oe,Moe].join(`
|
|
1616
1616
|
`),document.head.appendChild(e),!document.querySelector('meta[name="viewport"]')){let t=document.createElement("meta");t.name="viewport",t.content="width=device-width, initial-scale=1",document.head.appendChild(t)}document.documentElement.classList.add("austere"),document.documentElement.style.colorScheme="dark"}function PEt(e){if(!e||typeof e!="object")return;let t={};for(let[a,r]of Object.entries(e))if(!a.startsWith("$"))if(r&&typeof r=="object"&&!Array.isArray(r))if("value"in r&&Object.keys(r).length<=3)t[a]=r.value;else{let n=PEt(r);n&&Object.keys(n).length&&(t[a]=n)}else t[a]=r;return Object.keys(t).length?t:void 0}function g$a(){let e=window.parent&&window.parent!==window,t=new Map,a=r=>{e&&window.parent.postMessage({austere:1,...r},"*")};return window.addEventListener("message",r=>{if(r.source!==window.parent)return;let n=r.data;!n||n.austere!==1||typeof n.type!="string"||t.get(n.type)?.forEach(o=>o(n))}),{framed:e,connected:!1,send:a,on(r,n){return t.has(r)||t.set(r,new Set),t.get(r).add(n),()=>t.get(r).delete(n)}}}function $Et(e,t){e.framed?e.send({type:"open-url",url:t}):window.open(t,"_blank","noopener")}function _X(e){let t=document.createElement("div");t.className="austere-toast",t.setAttribute("data-austere-ui",""),t.textContent=e,document.body.appendChild(t),setTimeout(()=>t.classList.add("out"),2600),setTimeout(()=>t.remove(),3100)}function y$a(e){let t=[e.message];return e.form&&t.push(`form: ${JSON.stringify(e.form)}`),e.context!==void 0&&t.push(`context: ${JSON.stringify(e.context)}`),t.join(`
|
|
1617
1617
|
`)}var MX=null,BEt=new Set,bv=xv,EEt="";function x$a(e,t){BEt.add(e.name);let a=!e.bundled&&LX()?" (`austere-axi check <file>` says why)":"";Rc({source:"pack",component:e.name,message:`pack ${e.name}@${e.version}: ${t.message}${a}`})}function v$a(){let e=ys(),t=e.map(a=>`${a.name}@${a.version}`).join(",");if(t===EEt)return bv;EEt=t,TEt(e);try{bv=e.length?IX(e.flatMap(a=>a.components),{onSkip:(a,r)=>Rc({source:"pack",component:a.name,message:r})}):xv}catch(a){Rc({source:"pack",message:`packs could not be added (${a.message}); rendering without them`}),bv=xv}return window.__austere.library=bv,bv}async function FEt(e){MX||(MX=CEt());let t=AEt(e,MX).filter(a=>!BEt.has(a.name));return t.some(a=>!ys().some(r=>r.name===a.name))&&await NEt(t,{onError:x$a}),v$a()}function b$a({programRef:e,initialLibrary:t,bridge:a,annotator:r,initialState:n}){let[o,i]=(0,Pi.useState)({program:e.current,library:t}),l=o.program,s=(0,Pi.useRef)(null);(0,Pi.useEffect)(()=>a.on("source",async({program:f})=>{if(typeof f!="string"||f===e.current)return;let m=REt(e.current,f);e.current=f,r?.highlight([]);let x=await FEt(f);e.current===f&&(s.current=m,i({program:f,library:x}))}),[a]),(0,Pi.useEffect)(()=>a.on("reveal",({id:f})=>{r?.reveal(f,eh(e.current),L9)}),[a,r]),(0,Pi.useEffect)(()=>{let f=s.current;if(!f)return;s.current=null;let m=setTimeout(()=>{let x=eh(e.current),v=f.filter(w=>w!=="root");r?.flash(v,"changed",x,L9),a.send({type:"changes",ids:v})},120);return()=>clearTimeout(m)},[l,r,a]);let u=(0,Pi.useCallback)(f=>{if(f.type==="open_url"){let v=f.params?.url;typeof v=="string"&&/^(https?:|mailto:)/i.test(v)&&$Et(a,v);return}if(f.type!=="continue_conversation")return;let m={kind:"action",message:f.humanFriendlyMessage||"(button)"},x=PEt(f.formState);if(x&&(m.form=x),f.params?.context!==void 0&&(m.context=f.params.context),a.connected)a.send({type:"action",item:m}),_X("Queued for the agent \u2014 press Send when ready");else{let v=y$a(m);navigator.clipboard?.writeText(v).then(()=>_X("Copied \u2014 paste it to your agent"),()=>_X(v))}},[a]),d=(0,Pi.useCallback)(f=>{a.send({type:"errors",errors:(f||[]).map(m=>({source:m.source,code:m.code,statementId:m.statementId,message:m.message,hint:m.hint}))})},[a]),p=(0,Pi.useCallback)(f=>a.send({type:"state",state:f}),[a]);return(0,kv.jsx)(Soe,{mode:"dark",children:(0,kv.jsx)("main",{className:"austere-page",children:(0,kv.jsx)(b2,{response:l,library:o.library,isStreaming:!1,onAction:u,onError:d,onStateUpdate:p,initialState:n})})})}function DEt(){h$a();let e=document.querySelector(m$a),t=e?e.textContent:"",a=document.createElement("div");a.id="austere-root",document.body.appendChild(a);let r=g$a(),n={current:t},o=null,i=null,l=FEt(t),s=p=>i||(i=l.then(f=>(0,OEt.createRoot)(a).render((0,kv.jsx)(b$a,{programRef:n,initialLibrary:f,bridge:r,annotator:o,initialState:p}))));if(!r.framed){s(void 0);return}let u={program:null,map:null};o=SEt({post:p=>r.send(p),lookup:()=>(u.program!==n.current&&(u={program:n.current,map:eh(n.current)}),[u.map,L9])}),r.on("highlight",({ids:p,scroll:f})=>{o.highlight(Array.isArray(p)?p.filter(m=>typeof m=="string"):[],!!f)}),document.addEventListener("click",p=>{if(p.defaultPrevented||p.button!==0)return;let f=p.target.closest?.("a[href]");if(!f||!/^(https?|mailto):/i.test(f.href)||f.protocol===location.protocol&&f.host===location.host)return;let m=(f.getAttribute("target")||"").toLowerCase();!m||m==="_self"||(p.preventDefault(),$Et(r,f.href))}),nee(p=>r.send({type:"runtime-error",error:p})),r.on("init",async p=>{if(r.connected=!0,o.setMode(p.mode),await s(p.state||void 0),p.scrollY>0){let f=0,m=()=>{window.scrollTo(0,p.scrollY),Math.abs(window.scrollY-p.scrollY)>2&&++f<20&&setTimeout(m,50)};setTimeout(m,30)}r.send({type:"ready",title:document.title,version:CX})}),r.on("mode",p=>o.setMode(p.mode)),window.addEventListener("scroll",()=>r.send({type:"scroll",y:window.scrollY}),{passive:!0}),r.send({type:"hello",title:document.title,version:CX}),setTimeout(()=>s(void 0),600)}window.__austere={version:CX,library:xv,packs:ys};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",DEt,{once:!0}):DEt();})();
|
package/dist/catalog.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"format":1,"pack":"core","version":"0.5.1","groups":[{"name":"Layout","notes":["- A page is root = Stack([...sections], \"column\", \"l\"). Each section is a Card([CardHeader(title, subtitle), ...content]).","- Side by side: Stack([a, b], \"row\", \"m\", \"stretch\", \"start\", true). Cards in a row share the width.","- Tabs for alternative views, Accordion for detail the reader may skip, Steps for ordered procedures. Several blocks in one Card: label each with InlineHeader.","- Card children must match its list; anything else (Accordion, Tag, a Callout row) can sit in a Stack inside the Card, or directly in root's Stack."]},{"name":"Content","notes":["- MarkDownRenderer for prose, bullet lists and inline code; one statement per paragraph group so each is annotatable.","- Callout for the one thing the reader must not miss: a risk, a decision needed, a caveat.","- CodeBlock for a whole snippet. Image src may be a path relative to the artifact file.","- Architecture for systems: services, stores, queues, trust boundaries. Name every Node, Edge and Group. Over ~15 nodes, use lanes or split the diagram.","- lanes: for systems split by owner, repo or tier. Groups are the columns, left to right as listed; put every node in one, in reading order (plain groups for a heading without a frame). About 4 columns fit a laptop; wider ones scroll (check warns). Phones get the lanes stacked as bands. Pin row only to put boxes side by side or line them up.","- Diff for code changes: show the hunks that matter, not whole files. Hunk counts are recomputed, so only start lines matter.","- Mermaid for sequences, state machines, ER, gantt and quick flowcharts."]},{"name":"Data","notes":["- Table is COLUMN-oriented: Table([Col(\"Option\", names), Col(\"Effort\", efforts), Col(\"Risk\", risks)]). Col data may mix strings and components, e.g. [\"n/a\", Tag(\"high\", null, \"sm\", \"danger\")]. Cells are plain text (no markdown) and wrap; Col type \"number\" for figures.","- EntityList for key/value facts; OverviewCardBlock + OverviewCardItem + MetricIndicatorInline for a KPI row.","- EditableTable when the reviewer should correct or fill in values; edits arrive with the next @ToAssistant from its Form.","- Icon names are lucide kebab-case (circle-check, triangle-alert, git-branch)."]},{"name":"Charts","notes":["- Charts take column arrays: BarChart(labels, [Series(\"p50\", [..]), Series(\"p99\", [..])], \"grouped\", \"Week\", \"ms\").","- PieChart(labels, values) with plain number arrays."]},{"name":"Forms","notes":["- Form(name, buttons, fields). Define each FormControl as its own statement. Never nest a Form in a Form.","- To ask the reviewer to decide: OptionCards or RadioGroup inside a Form whose button is Button(\"Send decision\", @ToAssistant(\"Decision: rollout strategy\"), \"primary\"). The values arrive with that message as form: {<formName>: {<fieldName>: value}}; no context needed. Reviewers can always annotate and message, so add a notes field only when it belongs with the decision.","- OptionCards(\"pick\", \"single\", [OptionCard(\"a\", \"Option A\", \"why\", Icon(\"zap\")), OptionCard(\"b\", \"Option B\")], {required: true}, \"a\") — the last argument pre-selects.","- rules: {required: true, minLength: 10, ...}; the renderer shows the messages."]},{"name":"Buttons","notes":["- @ToAssistant(message, context?) queues a message to the agent; @OpenUrl(url) opens a link. A Button with no action sends its label.","- Use buttons for follow-ups the reviewer can pick in one click: \"Go with option B\", \"Split this into two PRs\"."]}],"components":[{"name":"Card","group":"Layout","signature":"Card(children: (TextContent | MarkDownRenderer | CardHeader | Callout | CodeBlock | Image | Separator | HorizontalBarChart | PieChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | InlineHeader | EntityList | EditableTable | OverviewCardBlock | Tabs | Stack | Architecture | Diff | FileTree | Mermaid | Progress | Avatar | AvatarGroup | Tooltip | HoverCard | Breadcrumb | Kbd | Skeleton | Calendar | Timeline)[], variant?: \"card\" | \"sunk\" | \"clear\", direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean)","description":"Styled container. variant: \"card\" (default, elevated) | \"sunk\" (recessed) | \"clear\" (transparent). Always full width. Accepts all Stack flex params (default: direction \"column\"). Cards flex to share space in row/wrap layouts.","tier":"core","pack":"core","examples":[]},{"name":"CardHeader","group":"Layout","signature":"CardHeader(title?: string, subtitle?: string)","description":"Header with optional title and subtitle","tier":"core","pack":"core","examples":[]},{"name":"TextContent","group":"Content","signature":"TextContent(text: string, size?: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\")","description":"Text block. Supports markdown. Optional size: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\".","tier":"core","pack":"core","examples":[]},{"name":"MarkDownRenderer","group":"Content","signature":"MarkDownRenderer(textMarkdown: string, variant?: \"clear\" | \"card\" | \"sunk\")","description":"Renders markdown text with optional container variant","tier":"core","pack":"core","examples":[]},{"name":"Callout","group":"Content","signature":"Callout(variant: \"info\" | \"warning\" | \"error\" | \"success\" | \"neutral\", title: string, description: string, visible?: $binding<boolean>)","description":"Callout banner. Optional visible is a reactive $boolean — auto-dismisses after 3s by setting $visible to false.","tier":"core","pack":"core","examples":[]},{"name":"Image","group":"Content","signature":"Image(alt: string, src?: string)","description":"Image with alt text and optional URL","tier":"core","pack":"core","examples":[]},{"name":"CodeBlock","group":"Content","signature":"CodeBlock(language: string, codeString: string)","description":"Syntax-highlighted code block","tier":"core","pack":"core","examples":[]},{"name":"InlineHeader","group":"Layout","signature":"InlineHeader(heading: string, description?: string)","description":"Compact section heading with an optional one-line description, for use inside cards.","tier":"core","pack":"core","examples":[]},{"name":"Table","group":"Data","signature":"Table(columns: Col[])","description":"Data table — column-oriented. Each Col holds its own data array.","tier":"core","pack":"core","examples":[]},{"name":"Col","group":"Data","signature":"Col(label: string, data: any, type?: \"string\" | \"number\" | \"action\")","description":"Column definition — holds label + data array","tier":"core","pack":"core","examples":[]},{"name":"EditableTable","group":"Data","signature":"EditableTable(name?: string, columns?: {type: \"text\" | \"number\" | \"date-single\" | \"select\" | \"url\", key?: string, header?: string, width?: number, options?: {value: string, label: string}[]}[], data?: {id: string, values: (string | number)[]}[])","description":"Spreadsheet-like table whose cells the user can edit inline (text, number, url, date, select columns); edits are saved back as a form field","tier":"extended","pack":"core","examples":[]},{"name":"BarChart","group":"Charts","signature":"BarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string, height?: number)","description":"Vertical bars; use for comparing values across categories with one or more series","tier":"core","pack":"core","examples":[]},{"name":"LineChart","group":"Charts","signature":"LineChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string, height?: number)","description":"Lines over categories; use for trends and continuous data over time","tier":"core","pack":"core","examples":[]},{"name":"AreaChart","group":"Charts","signature":"AreaChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string, height?: number)","description":"Filled area under lines; use for cumulative totals or volume trends over time","tier":"extended","pack":"core","examples":[]},{"name":"HorizontalBarChart","group":"Charts","signature":"HorizontalBarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string)","description":"Horizontal bars; prefer when category labels are long or for ranked lists","tier":"extended","pack":"core","examples":[]},{"name":"Series","group":"Charts","signature":"Series(category: string, values: number[])","description":"One data series","tier":"core","pack":"core","examples":[]},{"name":"PieChart","group":"Charts","signature":"PieChart(labels: string[], values: number[], variant?: \"pie\" | \"donut\", appearance?: \"circular\" | \"semiCircular\")","description":"Circular slices; use plucked arrays: PieChart(data.categories, data.values)","tier":"core","pack":"core","examples":[]},{"name":"ScatterChart","group":"Charts","signature":"ScatterChart(datasets: ScatterSeries[], xLabel?: string, yLabel?: string)","description":"X/Y scatter plot; use for correlations, distributions, and clustering","tier":"extended","pack":"core","examples":[]},{"name":"ScatterSeries","group":"Charts","signature":"ScatterSeries(name: string, points: Point[])","description":"Named dataset","tier":"extended","pack":"core","examples":[]},{"name":"Point","group":"Charts","signature":"Point(x: number, y: number, z?: number)","description":"Data point with numeric coordinates","tier":"extended","pack":"core","examples":[]},{"name":"Form","group":"Forms","signature":"Form(name: string, buttons: Buttons, fields?: FormControl[])","description":"Form container with fields and explicit action buttons","tier":"core","pack":"core","examples":[]},{"name":"FormControl","group":"Forms","signature":"FormControl(label: string, input: Input | TextArea | Select | Slider | CheckBoxGroup | RadioGroup | Chips | OptionCards, hint?: string)","description":"Field with label, input component, and optional hint text","tier":"core","pack":"core","examples":[]},{"name":"Label","group":"Forms","signature":"Label(text: string)","description":"Text label","tier":"extended","pack":"core","examples":[]},{"name":"Input","group":"Forms","signature":"Input(name: string, placeholder?: string, type?: \"text\" | \"email\" | \"password\" | \"number\" | \"url\", rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>)","description":"","tier":"core","pack":"core","examples":[]},{"name":"TextArea","group":"Forms","signature":"TextArea(name: string, placeholder?: string, rows?: number, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>)","description":"","tier":"core","pack":"core","examples":[]},{"name":"Select","group":"Forms","signature":"Select(name: string, items: SelectItem[], placeholder?: string, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>, size?: \"small\" | \"medium\" | \"large\")","description":"","tier":"core","pack":"core","examples":[]},{"name":"SelectItem","group":"Forms","signature":"SelectItem(value: string, label: string)","description":"Option for Select","tier":"core","pack":"core","examples":[]},{"name":"Slider","group":"Forms","signature":"Slider(name: string, variant: \"continuous\" | \"discrete\", min: number, max: number, step?: number, defaultValue?: number[], label?: string, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<number[]>)","description":"Numeric slider input; supports continuous and discrete (stepped) variants","tier":"extended","pack":"core","examples":[]},{"name":"CheckBoxGroup","group":"Forms","signature":"CheckBoxGroup(name: string, items: CheckBoxItem[], rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<Record<string, boolean>>)","description":"","tier":"extended","pack":"core","examples":[]},{"name":"CheckBoxItem","group":"Forms","signature":"CheckBoxItem(label: string, description: string, name: string, defaultChecked?: boolean)","description":"","tier":"extended","pack":"core","examples":[]},{"name":"RadioGroup","group":"Forms","signature":"RadioGroup(name: string, items: RadioItem[], defaultValue?: string, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>)","description":"","tier":"core","pack":"core","examples":[]},{"name":"RadioItem","group":"Forms","signature":"RadioItem(label: string, description: string, value: string)","description":"","tier":"core","pack":"core","examples":[]},{"name":"SwitchGroup","group":"Forms","signature":"SwitchGroup(name: string, items: SwitchItem[], variant?: \"clear\" | \"card\" | \"sunk\", value?: $binding<Record<string, boolean>>)","description":"Group of switch toggles","tier":"extended","pack":"core","examples":[]},{"name":"SwitchItem","group":"Forms","signature":"SwitchItem(label?: string, description?: string, name: string, defaultChecked?: boolean)","description":"Individual switch toggle","tier":"extended","pack":"core","examples":[]},{"name":"ChipItem","group":"Forms","signature":"ChipItem(value: string, label: string, icon?: Icon, disabled?: boolean)","description":"A single selectable chip inside a Chips group, with a value, label and optional icon.","tier":"extended","pack":"core","examples":[]},{"name":"Chips","group":"Forms","signature":"Chips(name: string, type?: \"single\" | \"multiple\", items?: ChipItem[], rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, defaultValue?: string | string[])","description":"A form field of compact selectable chips for choosing one or many short options; the selection is stored under `name`.","tier":"extended","pack":"core","examples":[]},{"name":"OptionCard","group":"Forms","signature":"OptionCard(value: string, title: string, subtitle?: string, topContent?: Icon | Image, disabled?: boolean)","description":"A single selectable card inside an OptionCards group, with a value, title, optional subtitle and an optional Icon or Image on top.","tier":"core","pack":"core","examples":[]},{"name":"OptionCards","group":"Forms","signature":"OptionCards(name: string, type?: \"single\" | \"multiple\", items?: OptionCard[], rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, defaultValue?: string | string[])","description":"A form field of selectable cards (title, optional subtitle, optional icon or image) laid out in a responsive grid for choosing one or many options; the selection is stored under `name`.","tier":"core","pack":"core","examples":[]},{"name":"Button","group":"Buttons","signature":"Button(label: string, action?: ActionExpression, variant?: \"primary\" | \"secondary\" | \"tertiary\", type?: \"normal\" | \"destructive\", size?: \"extra-small\" | \"small\" | \"medium\" | \"large\")","description":"Clickable button","tier":"core","pack":"core","examples":[]},{"name":"Buttons","group":"Buttons","signature":"Buttons(buttons: Button[], direction?: \"row\" | \"column\")","description":"Group of Button components. direction: \"row\" (default) | \"column\".","tier":"core","pack":"core","examples":[]},{"name":"Stack","group":"Layout","signature":"Stack(children: any[], direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean)","description":"Flex container. direction: \"row\"|\"column\" (default \"column\"). gap: \"none\"|\"xs\"|\"s\"|\"m\"|\"l\"|\"xl\"|\"2xl\" (default \"m\"). align: \"start\"|\"center\"|\"end\"|\"stretch\"|\"baseline\". justify: \"start\"|\"center\"|\"end\"|\"between\"|\"around\"|\"evenly\".","tier":"core","pack":"core","examples":[]},{"name":"Tabs","group":"Layout","signature":"Tabs(items: TabItem[])","description":"Tabbed container","tier":"core","pack":"core","examples":[]},{"name":"TabItem","group":"Layout","signature":"TabItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | CodeBlock | Image | Separator | HorizontalBarChart | PieChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | InlineHeader | EntityList | EditableTable | OverviewCardBlock | Architecture | Diff | FileTree | Mermaid | Progress | Avatar | AvatarGroup | Tooltip | HoverCard | Breadcrumb | Kbd | Skeleton | Calendar | Timeline)[])","description":"value is unique id, trigger is tab label, content is array of components","tier":"core","pack":"core","examples":[]},{"name":"Accordion","group":"Layout","signature":"Accordion(items: AccordionItem[])","description":"Collapsible sections","tier":"core","pack":"core","examples":[]},{"name":"AccordionItem","group":"Layout","signature":"AccordionItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | CodeBlock | Image | Separator | HorizontalBarChart | PieChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | InlineHeader | EntityList | EditableTable | OverviewCardBlock | Architecture | Diff | FileTree | Mermaid | Progress | Avatar | AvatarGroup | Tooltip | HoverCard | Breadcrumb | Kbd | Skeleton | Calendar | Timeline)[])","description":"value is unique id, trigger is section title","tier":"core","pack":"core","examples":[]},{"name":"Steps","group":"Layout","signature":"Steps(items: StepsItem[])","description":"Step-by-step guide","tier":"core","pack":"core","examples":[]},{"name":"StepsItem","group":"Layout","signature":"StepsItem(title: string, details: string)","description":"title and details text for one step","tier":"core","pack":"core","examples":[]},{"name":"Separator","group":"Layout","signature":"Separator(orientation?: \"horizontal\" | \"vertical\", decorative?: boolean)","description":"Visual divider between content sections","tier":"core","pack":"core","examples":[]},{"name":"TagBlock","group":"Data","signature":"TagBlock(tags: string[], size?: \"sm\" | \"md\" | \"lg\")","description":"tags is an array of strings; optional size sm | md | lg","tier":"extended","pack":"core","examples":[]},{"name":"Tag","group":"Data","signature":"Tag(text: string, icon?: Icon, size?: \"sm\" | \"md\" | \"lg\", variant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\")","description":"Styled tag/badge with optional Icon and variant","tier":"core","pack":"core","examples":[]},{"name":"Icon","group":"Data","signature":"Icon(name: string, category?: string)","description":"A lucide icon by kebab-case name (e.g. 'circle-check'). Optional category picks a topical fallback when the name doesn't resolve.","tier":"core","pack":"core","examples":[]},{"name":"EntityList","group":"Data","signature":"EntityList(rows?: {left: string, right: string, rightVariant?: \"text\" | \"number\"}[], size?: \"small\" | \"default\", header?: {left: string, right: string, rightVariant?: \"text\" | \"number\"}, footer?: {left: string, right: string, rightVariant?: \"text\" | \"number\"})","description":"Two-column key/value rows (left label, right value). size 'default' supports optional header and footer rows; rightVariant 'number' uses tabular numbers.","tier":"core","pack":"core","examples":[]},{"name":"Text","group":"Data","signature":"Text(variant?: \"text\" | \"number\", value: string, subtext?: string, subtextVariant?: \"text\" | \"number\" | \"metric\", size?: \"xs\" | \"sm\" | \"md\" | \"lg\")","description":"Plain text line with optional subtext. variant 'number' uses tabular number styling; subtextVariant 'metric' colors a leading +/- subtext green/red.","tier":"core","pack":"core","examples":[]},{"name":"BoldText","group":"Data","signature":"BoldText(variant?: \"text\" | \"number\", value: string, subtext?: string, subtextVariant?: \"text\" | \"number\" | \"metric\", size?: \"xs\" | \"sm\" | \"md\" | \"lg\")","description":"Emphasized (bold) text line with optional subtext. variant 'number' uses tabular number styling; subtextVariant 'metric' colors a leading +/- subtext green/red.","tier":"extended","pack":"core","examples":[]},{"name":"IconText","group":"Data","signature":"IconText(icon: Icon, iconVariant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\" | \"inverted\" | \"filled\" | \"soft\", iconSize?: \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"sm\" | \"md\" | \"lg\", title: string, subtitle?: string, bold?: boolean, layout?: \"horizontal\" | \"vertical\")","description":"An icon badge with a title and optional subtitle, laid out horizontally or vertically. iconVariant sets the badge color.","tier":"extended","pack":"core","examples":[]},{"name":"MetricIndicatorInline","group":"Data","signature":"MetricIndicatorInline(value: string, subtext?: string, trend?: {direction: \"up\" | \"down\", value: number})","description":"Headline metric value with an optional +/- percentage trend and subtext, all on one line.","tier":"core","pack":"core","examples":[]},{"name":"OverviewCardItem","group":"Data","signature":"OverviewCardItem(id?: string, top: IconText | Text, bottom?: MetricIndicatorInline)","description":"One overview card: a heading slot at the top (IconText, ImageText or Text) and an optional MetricIndicatorInline at the bottom.","tier":"core","pack":"core","examples":[]},{"name":"OverviewCardBlock","group":"Data","signature":"OverviewCardBlock(items: OverviewCardItem[], layout?: \"grid\" | \"carousel\", responsive?: boolean, action?: ActionExpression, gap?: number | string)","description":"A grid or horizontal carousel of compact overview cards, each with a heading (icon/image/text) on top and an inline metric below; optionally clickable with a shared action.","tier":"core","pack":"core","examples":[]},{"name":"Architecture","group":"Content","signature":"Architecture(nodes: Node[], edges: Edge[], groups?: Group[], direction?: \"auto\" | \"right\" | \"down\" | \"lanes\")","description":"System diagram laid out automatically: write no coordinates. Every Node, Edge and Group is its own statement and click target. direction auto (default) runs right when that fits the page legibly, else down; lanes makes each top-level Group a column.","tier":"core","pack":"core","examples":["platformMap = Architecture([browser, edge, api, sessions, cache], [toEdge, toApi, readSessions, readCache], [vpc])\nbrowser = Node(\"Browser\", \"external\")\nedge = Node(\"Edge worker\", \"cloud\", \"Cloudflare\")\napi = Node(\"API\", \"backend\", \"Node :8080\")\nsessions = Node(\"Sessions\", \"database\", \"Postgres\", \"new\")\ncache = Node(\"Redis\", \"database\", \"read-through\")\ntoEdge = Edge(browser, edge, \"HTTPS\", \"emphasis\")\ntoApi = Edge(edge, api)\nreadSessions = Edge(api, sessions, \"SQL\")\nreadCache = Edge(api, cache, \"cache\", \"dashed\")\nvpc = Group(\"Platform VPC\", [api, sessions, cache])","ownership = Architecture([web, ordersApi, ledger, ordersDb, billingJob], [placeOrder, writeOrder, readOrders, postLedger], [clients, ordersRepo, billingRepo], \"lanes\")\nweb = Node(\"Web app\", \"frontend\")\nordersApi = Node(\"Orders API\", \"backend\", \"Node :8080\")\nordersDb = Node(\"orders table\", \"database\", \"Postgres\", null, \"success\")\nbillingJob = Node(\"Nightly billing\", \"backend\", \"cron 02:00\")\nledger = Node(\"Ledger\", \"database\", \"append-only\", null, \"info\")\nplaceOrder = Edge(web, ordersApi, \"POST /orders\")\nwriteOrder = Edge(ordersApi, ordersDb, \"insert\")\nreadOrders = Edge(billingJob, ordersDb, \"read unbilled\", null, \"danger\")\npostLedger = Edge(billingJob, ledger, \"post\")\nclients = Group(\"CLIENTS\", [web], \"plain\")\nordersRepo = Group(\"orders-service\", [ordersApi, ordersDb])\nbillingRepo = Group(\"billing\", [billingJob, ledger])"]},{"name":"Node","group":"Content","signature":"Node(label: string, kind?: \"frontend\" | \"backend\" | \"database\" | \"messagebus\" | \"cloud\" | \"security\" | \"external\", detail?: string, tag?: string, tone?: \"info\" | \"success\" | \"warning\" | \"danger\" | \"strong\", row?: number)","description":"A box in an Architecture. kind sets icon and color (default backend); detail is monospace, up to 2 lines (\\n breaks); tag is a small chip such as \"new\"; tone tints it (danger = risk, strong = where it ends); row pins it to a row (1, 2, ...) in lanes.","tier":"core","pack":"core","examples":[]},{"name":"Edge","group":"Content","signature":"Edge(from: Node, to: Node, label?: string, style?: \"solid\" | \"dashed\" | \"emphasis\" | \"security\", tone?: \"info\" | \"success\" | \"warning\" | \"danger\")","description":"An arrow between two Node statements (pass their names, not strings). style: dashed for async, emphasis for the main path, security for auth or trust flows. tone colors it, e.g. danger for a risky write, success for a read.","tier":"core","pack":"core","examples":[]},{"name":"Group","group":"Content","signature":"Group(label: string, members: Node[], kind?: \"region\" | \"security\" | \"plain\")","description":"A boundary around Node statements (a VPC, a cluster, a trust zone); members still sit where their edges put them. A group whose members are a subset of another's is drawn inside it; kind security draws it red, plain draws only its name.","tier":"core","pack":"core","examples":[]},{"name":"Diff","group":"Content","signature":"Diff(patch: string, title?: string)","description":"Unified diff (git diff output, one or more files) with line numbers. patch is a raw multi-line string. Clicked lines reach the agent as file:+line.","tier":"core","pack":"core","examples":["retryPatch = Diff(\"diff --git a/src/retry.ts b/src/retry.ts\n--- a/src/retry.ts\n+++ b/src/retry.ts\n@@ -10,2 +10,3 @@\n- for (let i = 0; i < 3; i++) {\n+ for (let i = 0; i < MAX_ATTEMPTS; i++) {\n+ if (i > 0) await sleep(backoff(i));\")"]},{"name":"FileTree","group":"Data","signature":"FileTree(entries: string[])","description":"File tree, one path per entry, optionally prefixed with a git status code (A new, M modified, D deleted, R old -> new) and suffixed with \" # note\". Folders are inferred. Clicked files and folders reach the agent by path.","tier":"core","pack":"core","examples":["changedFiles = FileTree([\"M src/session/store.ts # read-through to Postgres\", \"A src/session/pg-store.ts\", \"A migrations/0042_sessions.sql # table + expiry index\", \"R src/session/redis.ts -> src/session/redis-cache.ts\", \"D src/session/legacy.ts\", \"M src/config.ts # SESSIONS_PG flag\"])"]},{"name":"Mermaid","group":"Content","signature":"Mermaid(source: string, caption?: string)","description":"Diagram from Mermaid source (flowchart, sequence, state, class, ER, gantt). source is a raw multi-line string. Keep node labels to a few words; clicked nodes reach the agent by label.","tier":"core","pack":"@austere-axi/pack-mermaid","examples":["requestPath = Mermaid(\"flowchart LR\n client[Client] --> api[API]\n api --> pg[(Postgres)]\", \"Request path\")"]},{"name":"Progress","group":"Data","signature":"Progress(value: number, label?: string, max?: number)","description":"Progress bar. value counts toward max (default 100); label names what is progressing. Shows a percentage.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["migration = Progress(64, \"Rows migrated\")"]},{"name":"Avatar","group":"Data","signature":"Avatar(name: string, src?: string, size?: \"md\" | \"lg\")","description":"Round avatar for a person. Shows the initials of name; src is an optional https image URL.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["owner = Avatar(\"Ada Lovelace\")"]},{"name":"AvatarGroup","group":"Data","signature":"AvatarGroup(avatars: Avatar[], max?: number)","description":"Overlapping Avatars, for reviewers or owners. max (default 4) shows the rest as +N.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["team = AvatarGroup([ada, grace, linus], 2)\nada = Avatar(\"Ada Lovelace\")\ngrace = Avatar(\"Grace Hopper\")\nlinus = Avatar(\"Linus Torvalds\")"]},{"name":"Tooltip","group":"Content","signature":"Tooltip(text: string, tip: string)","description":"Inline text with a short hint on hover or focus (a term and its definition). Keep tip to one line.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["term = Tooltip(\"idempotent\", \"Safe to run twice with the same result.\")"]},{"name":"HoverCard","group":"Content","signature":"HoverCard(text: string, title: string, body?: string)","description":"Inline text that shows a small card (title and a line or two of body) on hover or focus, e.g. a person or a service.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["svc = HoverCard(\"billing-api\", \"billing-api\", \"Owns invoices and refunds. On call: payments team.\")"]},{"name":"Breadcrumb","group":"Content","signature":"Breadcrumb(items: BreadcrumbItem[])","description":"Path trail such as Repo / Package / File, from BreadcrumbItems. Each item is a click target.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["trail = Breadcrumb([repo, pkg, file])\nrepo = BreadcrumbItem(\"austere-axi\")\npkg = BreadcrumbItem(\"packs\")\nfile = BreadcrumbItem(\"shadcn\")"]},{"name":"BreadcrumbItem","group":"Content","signature":"BreadcrumbItem(label: string, href?: string)","description":"One step of a Breadcrumb. href is optional; the last item is the current page.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":[]},{"name":"Kbd","group":"Content","signature":"Kbd(keys: string)","description":"Keyboard shortcut. keys joins keys with \"+\", e.g. \"Ctrl+K\"; each key is drawn as a key cap.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["shortcut = Kbd(\"Ctrl+Shift+P\")"]},{"name":"Skeleton","group":"Content","signature":"Skeleton(lines?: number, shape?: \"lines\" | \"avatar\")","description":"Grey placeholder block for content not yet written or loaded (default 3 lines). shape avatar adds a round head.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["pending = Skeleton(3, \"avatar\")"]},{"name":"Calendar","group":"Data","signature":"Calendar(month: string, highlights?: string[])","description":"Read-only month grid (not a date picker). month is \"YYYY-MM\"; highlights lists \"YYYY-MM-DD\" or \"YYYY-MM-DD label\" entries to mark, e.g. a freeze or a release. Marked days are click targets.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["window = Calendar(\"2026-11\", [\"2026-11-04 Code freeze\", \"2026-11-12 Release\", \"2026-11-13\"])"]},{"name":"Timeline","group":"Content","signature":"Timeline(items: TimelineItem[])","description":"Vertical history or schedule of TimelineItems, oldest first. Each item is a click target.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["history = Timeline([found, fixed, rollout])\nfound = TimelineItem(\"Bug found\", \"Oct 28\", \"Retries double-charge on timeout.\")\nfixed = TimelineItem(\"Fix merged\", \"Oct 29\", \"Idempotency key added.\", \"current\")\nrollout = TimelineItem(\"Rollout\", \"Nov 3\", \"\", \"upcoming\")"]},{"name":"TimelineItem","group":"Content","signature":"TimelineItem(title: string, date?: string, detail?: string, state?: \"done\" | \"current\" | \"upcoming\")","description":"One event in a Timeline. state: done (default), current or upcoming.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":[]}]}
|
|
1
|
+
{"format":1,"pack":"core","version":"0.5.2","groups":[{"name":"Layout","notes":["- A page is root = Stack([...sections], \"column\", \"l\"). Each section is a Card([CardHeader(title, subtitle), ...content]).","- Side by side: Stack([a, b], \"row\", \"m\", \"stretch\", \"start\", true). Cards in a row share the width.","- Tabs for alternative views, Accordion for detail the reader may skip, Steps for ordered procedures. Several blocks in one Card: label each with InlineHeader.","- Card children must match its list; anything else (Accordion, Tag, a Callout row) can sit in a Stack inside the Card, or directly in root's Stack."]},{"name":"Content","notes":["- MarkDownRenderer for prose, bullet lists and inline code; one statement per paragraph group so each is annotatable.","- Callout for the one thing the reader must not miss: a risk, a decision needed, a caveat.","- CodeBlock for a whole snippet. Image src may be a path relative to the artifact file.","- Architecture for systems: services, stores, queues, trust boundaries. Name every Node, Edge and Group. Over ~15 nodes, use lanes or split the diagram.","- lanes: for systems split by owner, repo or tier. Groups are the columns, left to right as listed; put every node in one, in reading order (plain groups for a heading without a frame). About 4 columns fit a laptop; wider ones scroll (check warns). Phones get the lanes stacked as bands. Pin row only to put boxes side by side or line them up.","- Diff for code changes: show the hunks that matter, not whole files. Hunk counts are recomputed, so only start lines matter.","- Mermaid for sequences, state machines, ER, gantt and quick flowcharts."]},{"name":"Data","notes":["- Table is COLUMN-oriented: Table([Col(\"Option\", names), Col(\"Effort\", efforts), Col(\"Risk\", risks)]). Col data may mix strings and components, e.g. [\"n/a\", Tag(\"high\", null, \"sm\", \"danger\")]. Cells are plain text (no markdown) and wrap; Col type \"number\" for figures.","- EntityList for key/value facts; OverviewCardBlock + OverviewCardItem + MetricIndicatorInline for a KPI row.","- EditableTable when the reviewer should correct or fill in values; edits arrive with the next @ToAssistant from its Form.","- Icon names are lucide kebab-case (circle-check, triangle-alert, git-branch)."]},{"name":"Charts","notes":["- Charts take column arrays: BarChart(labels, [Series(\"p50\", [..]), Series(\"p99\", [..])], \"grouped\", \"Week\", \"ms\").","- PieChart(labels, values) with plain number arrays."]},{"name":"Forms","notes":["- Form(name, buttons, fields). Define each FormControl as its own statement. Never nest a Form in a Form.","- To ask the reviewer to decide: OptionCards or RadioGroup inside a Form whose button is Button(\"Send decision\", @ToAssistant(\"Decision: rollout strategy\"), \"primary\"). The values arrive with that message as form: {<formName>: {<fieldName>: value}}; no context needed. Reviewers can always annotate and message, so add a notes field only when it belongs with the decision.","- OptionCards(\"pick\", \"single\", [OptionCard(\"a\", \"Option A\", \"why\", Icon(\"zap\")), OptionCard(\"b\", \"Option B\")], {required: true}, \"a\") — the last argument pre-selects.","- rules: {required: true, minLength: 10, ...}; the renderer shows the messages."]},{"name":"Buttons","notes":["- @ToAssistant(message, context?) queues a message to the agent; @OpenUrl(url) opens a link. A Button with no action sends its label.","- Use buttons for follow-ups the reviewer can pick in one click: \"Go with option B\", \"Split this into two PRs\"."]}],"components":[{"name":"Card","group":"Layout","signature":"Card(children: (TextContent | MarkDownRenderer | CardHeader | Callout | CodeBlock | Image | Separator | HorizontalBarChart | PieChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | InlineHeader | EntityList | EditableTable | OverviewCardBlock | Tabs | Stack | Architecture | Diff | FileTree | Mermaid | Progress | Avatar | AvatarGroup | Tooltip | HoverCard | Breadcrumb | Kbd | Skeleton | Calendar | Timeline)[], variant?: \"card\" | \"sunk\" | \"clear\", direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean)","description":"Styled container. variant: \"card\" (default, elevated) | \"sunk\" (recessed) | \"clear\" (transparent). Always full width. Accepts all Stack flex params (default: direction \"column\"). Cards flex to share space in row/wrap layouts.","tier":"core","pack":"core","examples":[]},{"name":"CardHeader","group":"Layout","signature":"CardHeader(title?: string, subtitle?: string)","description":"Header with optional title and subtitle","tier":"core","pack":"core","examples":[]},{"name":"TextContent","group":"Content","signature":"TextContent(text: string, size?: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\")","description":"Text block. Supports markdown. Optional size: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\".","tier":"core","pack":"core","examples":[]},{"name":"MarkDownRenderer","group":"Content","signature":"MarkDownRenderer(textMarkdown: string, variant?: \"clear\" | \"card\" | \"sunk\")","description":"Renders markdown text with optional container variant","tier":"core","pack":"core","examples":[]},{"name":"Callout","group":"Content","signature":"Callout(variant: \"info\" | \"warning\" | \"error\" | \"success\" | \"neutral\", title: string, description: string, visible?: $binding<boolean>)","description":"Callout banner. Optional visible is a reactive $boolean — auto-dismisses after 3s by setting $visible to false.","tier":"core","pack":"core","examples":[]},{"name":"Image","group":"Content","signature":"Image(alt: string, src?: string)","description":"Image with alt text and optional URL","tier":"core","pack":"core","examples":[]},{"name":"CodeBlock","group":"Content","signature":"CodeBlock(language: string, codeString: string)","description":"Syntax-highlighted code block","tier":"core","pack":"core","examples":[]},{"name":"InlineHeader","group":"Layout","signature":"InlineHeader(heading: string, description?: string)","description":"Compact section heading with an optional one-line description, for use inside cards.","tier":"core","pack":"core","examples":[]},{"name":"Table","group":"Data","signature":"Table(columns: Col[])","description":"Data table — column-oriented. Each Col holds its own data array.","tier":"core","pack":"core","examples":[]},{"name":"Col","group":"Data","signature":"Col(label: string, data: any, type?: \"string\" | \"number\" | \"action\")","description":"Column definition — holds label + data array","tier":"core","pack":"core","examples":[]},{"name":"EditableTable","group":"Data","signature":"EditableTable(name?: string, columns?: {type: \"text\" | \"number\" | \"date-single\" | \"select\" | \"url\", key?: string, header?: string, width?: number, options?: {value: string, label: string}[]}[], data?: {id: string, values: (string | number)[]}[])","description":"Spreadsheet-like table whose cells the user can edit inline (text, number, url, date, select columns); edits are saved back as a form field","tier":"extended","pack":"core","examples":[]},{"name":"BarChart","group":"Charts","signature":"BarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string, height?: number)","description":"Vertical bars; use for comparing values across categories with one or more series","tier":"core","pack":"core","examples":[]},{"name":"LineChart","group":"Charts","signature":"LineChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string, height?: number)","description":"Lines over categories; use for trends and continuous data over time","tier":"core","pack":"core","examples":[]},{"name":"AreaChart","group":"Charts","signature":"AreaChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string, height?: number)","description":"Filled area under lines; use for cumulative totals or volume trends over time","tier":"extended","pack":"core","examples":[]},{"name":"HorizontalBarChart","group":"Charts","signature":"HorizontalBarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string)","description":"Horizontal bars; prefer when category labels are long or for ranked lists","tier":"extended","pack":"core","examples":[]},{"name":"Series","group":"Charts","signature":"Series(category: string, values: number[])","description":"One data series","tier":"core","pack":"core","examples":[]},{"name":"PieChart","group":"Charts","signature":"PieChart(labels: string[], values: number[], variant?: \"pie\" | \"donut\", appearance?: \"circular\" | \"semiCircular\")","description":"Circular slices; use plucked arrays: PieChart(data.categories, data.values)","tier":"core","pack":"core","examples":[]},{"name":"ScatterChart","group":"Charts","signature":"ScatterChart(datasets: ScatterSeries[], xLabel?: string, yLabel?: string)","description":"X/Y scatter plot; use for correlations, distributions, and clustering","tier":"extended","pack":"core","examples":[]},{"name":"ScatterSeries","group":"Charts","signature":"ScatterSeries(name: string, points: Point[])","description":"Named dataset","tier":"extended","pack":"core","examples":[]},{"name":"Point","group":"Charts","signature":"Point(x: number, y: number, z?: number)","description":"Data point with numeric coordinates","tier":"extended","pack":"core","examples":[]},{"name":"Form","group":"Forms","signature":"Form(name: string, buttons: Buttons, fields?: FormControl[])","description":"Form container with fields and explicit action buttons","tier":"core","pack":"core","examples":[]},{"name":"FormControl","group":"Forms","signature":"FormControl(label: string, input: Input | TextArea | Select | Slider | CheckBoxGroup | RadioGroup | Chips | OptionCards, hint?: string)","description":"Field with label, input component, and optional hint text","tier":"core","pack":"core","examples":[]},{"name":"Label","group":"Forms","signature":"Label(text: string)","description":"Text label","tier":"extended","pack":"core","examples":[]},{"name":"Input","group":"Forms","signature":"Input(name: string, placeholder?: string, type?: \"text\" | \"email\" | \"password\" | \"number\" | \"url\", rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>)","description":"","tier":"core","pack":"core","examples":[]},{"name":"TextArea","group":"Forms","signature":"TextArea(name: string, placeholder?: string, rows?: number, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>)","description":"","tier":"core","pack":"core","examples":[]},{"name":"Select","group":"Forms","signature":"Select(name: string, items: SelectItem[], placeholder?: string, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>, size?: \"small\" | \"medium\" | \"large\")","description":"","tier":"core","pack":"core","examples":[]},{"name":"SelectItem","group":"Forms","signature":"SelectItem(value: string, label: string)","description":"Option for Select","tier":"core","pack":"core","examples":[]},{"name":"Slider","group":"Forms","signature":"Slider(name: string, variant: \"continuous\" | \"discrete\", min: number, max: number, step?: number, defaultValue?: number[], label?: string, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<number[]>)","description":"Numeric slider input; supports continuous and discrete (stepped) variants","tier":"extended","pack":"core","examples":[]},{"name":"CheckBoxGroup","group":"Forms","signature":"CheckBoxGroup(name: string, items: CheckBoxItem[], rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<Record<string, boolean>>)","description":"","tier":"extended","pack":"core","examples":[]},{"name":"CheckBoxItem","group":"Forms","signature":"CheckBoxItem(label: string, description: string, name: string, defaultChecked?: boolean)","description":"","tier":"extended","pack":"core","examples":[]},{"name":"RadioGroup","group":"Forms","signature":"RadioGroup(name: string, items: RadioItem[], defaultValue?: string, rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, value?: $binding<string>)","description":"","tier":"core","pack":"core","examples":[]},{"name":"RadioItem","group":"Forms","signature":"RadioItem(label: string, description: string, value: string)","description":"","tier":"core","pack":"core","examples":[]},{"name":"SwitchGroup","group":"Forms","signature":"SwitchGroup(name: string, items: SwitchItem[], variant?: \"clear\" | \"card\" | \"sunk\", value?: $binding<Record<string, boolean>>)","description":"Group of switch toggles","tier":"extended","pack":"core","examples":[]},{"name":"SwitchItem","group":"Forms","signature":"SwitchItem(label?: string, description?: string, name: string, defaultChecked?: boolean)","description":"Individual switch toggle","tier":"extended","pack":"core","examples":[]},{"name":"ChipItem","group":"Forms","signature":"ChipItem(value: string, label: string, icon?: Icon, disabled?: boolean)","description":"A single selectable chip inside a Chips group, with a value, label and optional icon.","tier":"extended","pack":"core","examples":[]},{"name":"Chips","group":"Forms","signature":"Chips(name: string, type?: \"single\" | \"multiple\", items?: ChipItem[], rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, defaultValue?: string | string[])","description":"A form field of compact selectable chips for choosing one or many short options; the selection is stored under `name`.","tier":"extended","pack":"core","examples":[]},{"name":"OptionCard","group":"Forms","signature":"OptionCard(value: string, title: string, subtitle?: string, topContent?: Icon | Image, disabled?: boolean)","description":"A single selectable card inside an OptionCards group, with a value, title, optional subtitle and an optional Icon or Image on top.","tier":"core","pack":"core","examples":[]},{"name":"OptionCards","group":"Forms","signature":"OptionCards(name: string, type?: \"single\" | \"multiple\", items?: OptionCard[], rules?: {required?: boolean, email?: boolean, url?: boolean, numeric?: boolean, min?: number, max?: number, minLength?: number, maxLength?: number, pattern?: string}, defaultValue?: string | string[])","description":"A form field of selectable cards (title, optional subtitle, optional icon or image) laid out in a responsive grid for choosing one or many options; the selection is stored under `name`.","tier":"core","pack":"core","examples":[]},{"name":"Button","group":"Buttons","signature":"Button(label: string, action?: ActionExpression, variant?: \"primary\" | \"secondary\" | \"tertiary\", type?: \"normal\" | \"destructive\", size?: \"extra-small\" | \"small\" | \"medium\" | \"large\")","description":"Clickable button","tier":"core","pack":"core","examples":[]},{"name":"Buttons","group":"Buttons","signature":"Buttons(buttons: Button[], direction?: \"row\" | \"column\")","description":"Group of Button components. direction: \"row\" (default) | \"column\".","tier":"core","pack":"core","examples":[]},{"name":"Stack","group":"Layout","signature":"Stack(children: any[], direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean)","description":"Flex container. direction: \"row\"|\"column\" (default \"column\"). gap: \"none\"|\"xs\"|\"s\"|\"m\"|\"l\"|\"xl\"|\"2xl\" (default \"m\"). align: \"start\"|\"center\"|\"end\"|\"stretch\"|\"baseline\". justify: \"start\"|\"center\"|\"end\"|\"between\"|\"around\"|\"evenly\".","tier":"core","pack":"core","examples":[]},{"name":"Tabs","group":"Layout","signature":"Tabs(items: TabItem[])","description":"Tabbed container","tier":"core","pack":"core","examples":[]},{"name":"TabItem","group":"Layout","signature":"TabItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | CodeBlock | Image | Separator | HorizontalBarChart | PieChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | InlineHeader | EntityList | EditableTable | OverviewCardBlock | Architecture | Diff | FileTree | Mermaid | Progress | Avatar | AvatarGroup | Tooltip | HoverCard | Breadcrumb | Kbd | Skeleton | Calendar | Timeline)[])","description":"value is unique id, trigger is tab label, content is array of components","tier":"core","pack":"core","examples":[]},{"name":"Accordion","group":"Layout","signature":"Accordion(items: AccordionItem[])","description":"Collapsible sections","tier":"core","pack":"core","examples":[]},{"name":"AccordionItem","group":"Layout","signature":"AccordionItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | CodeBlock | Image | Separator | HorizontalBarChart | PieChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | InlineHeader | EntityList | EditableTable | OverviewCardBlock | Architecture | Diff | FileTree | Mermaid | Progress | Avatar | AvatarGroup | Tooltip | HoverCard | Breadcrumb | Kbd | Skeleton | Calendar | Timeline)[])","description":"value is unique id, trigger is section title","tier":"core","pack":"core","examples":[]},{"name":"Steps","group":"Layout","signature":"Steps(items: StepsItem[])","description":"Step-by-step guide","tier":"core","pack":"core","examples":[]},{"name":"StepsItem","group":"Layout","signature":"StepsItem(title: string, details: string)","description":"title and details text for one step","tier":"core","pack":"core","examples":[]},{"name":"Separator","group":"Layout","signature":"Separator(orientation?: \"horizontal\" | \"vertical\", decorative?: boolean)","description":"Visual divider between content sections","tier":"core","pack":"core","examples":[]},{"name":"TagBlock","group":"Data","signature":"TagBlock(tags: string[], size?: \"sm\" | \"md\" | \"lg\")","description":"tags is an array of strings; optional size sm | md | lg","tier":"extended","pack":"core","examples":[]},{"name":"Tag","group":"Data","signature":"Tag(text: string, icon?: Icon, size?: \"sm\" | \"md\" | \"lg\", variant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\")","description":"Styled tag/badge with optional Icon and variant","tier":"core","pack":"core","examples":[]},{"name":"Icon","group":"Data","signature":"Icon(name: string, category?: string)","description":"A lucide icon by kebab-case name (e.g. 'circle-check'). Optional category picks a topical fallback when the name doesn't resolve.","tier":"core","pack":"core","examples":[]},{"name":"EntityList","group":"Data","signature":"EntityList(rows?: {left: string, right: string, rightVariant?: \"text\" | \"number\"}[], size?: \"small\" | \"default\", header?: {left: string, right: string, rightVariant?: \"text\" | \"number\"}, footer?: {left: string, right: string, rightVariant?: \"text\" | \"number\"})","description":"Two-column key/value rows (left label, right value). size 'default' supports optional header and footer rows; rightVariant 'number' uses tabular numbers.","tier":"core","pack":"core","examples":[]},{"name":"Text","group":"Data","signature":"Text(variant?: \"text\" | \"number\", value: string, subtext?: string, subtextVariant?: \"text\" | \"number\" | \"metric\", size?: \"xs\" | \"sm\" | \"md\" | \"lg\")","description":"Plain text line with optional subtext. variant 'number' uses tabular number styling; subtextVariant 'metric' colors a leading +/- subtext green/red.","tier":"core","pack":"core","examples":[]},{"name":"BoldText","group":"Data","signature":"BoldText(variant?: \"text\" | \"number\", value: string, subtext?: string, subtextVariant?: \"text\" | \"number\" | \"metric\", size?: \"xs\" | \"sm\" | \"md\" | \"lg\")","description":"Emphasized (bold) text line with optional subtext. variant 'number' uses tabular number styling; subtextVariant 'metric' colors a leading +/- subtext green/red.","tier":"extended","pack":"core","examples":[]},{"name":"IconText","group":"Data","signature":"IconText(icon: Icon, iconVariant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\" | \"inverted\" | \"filled\" | \"soft\", iconSize?: \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"sm\" | \"md\" | \"lg\", title: string, subtitle?: string, bold?: boolean, layout?: \"horizontal\" | \"vertical\")","description":"An icon badge with a title and optional subtitle, laid out horizontally or vertically. iconVariant sets the badge color.","tier":"extended","pack":"core","examples":[]},{"name":"MetricIndicatorInline","group":"Data","signature":"MetricIndicatorInline(value: string, subtext?: string, trend?: {direction: \"up\" | \"down\", value: number})","description":"Headline metric value with an optional +/- percentage trend and subtext, all on one line.","tier":"core","pack":"core","examples":[]},{"name":"OverviewCardItem","group":"Data","signature":"OverviewCardItem(id?: string, top: IconText | Text, bottom?: MetricIndicatorInline)","description":"One overview card: a heading slot at the top (IconText, ImageText or Text) and an optional MetricIndicatorInline at the bottom.","tier":"core","pack":"core","examples":[]},{"name":"OverviewCardBlock","group":"Data","signature":"OverviewCardBlock(items: OverviewCardItem[], layout?: \"grid\" | \"carousel\", responsive?: boolean, action?: ActionExpression, gap?: number | string)","description":"A grid or horizontal carousel of compact overview cards, each with a heading (icon/image/text) on top and an inline metric below; optionally clickable with a shared action.","tier":"core","pack":"core","examples":[]},{"name":"Architecture","group":"Content","signature":"Architecture(nodes: Node[], edges: Edge[], groups?: Group[], direction?: \"auto\" | \"right\" | \"down\" | \"lanes\")","description":"System diagram laid out automatically: write no coordinates. Every Node, Edge and Group is its own statement and click target. direction auto (default) runs right when that fits the page legibly, else down; lanes makes each top-level Group a column.","tier":"core","pack":"core","examples":["platformMap = Architecture([browser, edge, api, sessions, cache], [toEdge, toApi, readSessions, readCache], [vpc])\nbrowser = Node(\"Browser\", \"external\")\nedge = Node(\"Edge worker\", \"cloud\", \"Cloudflare\")\napi = Node(\"API\", \"backend\", \"Node :8080\")\nsessions = Node(\"Sessions\", \"database\", \"Postgres\", \"new\")\ncache = Node(\"Redis\", \"database\", \"read-through\")\ntoEdge = Edge(browser, edge, \"HTTPS\", \"emphasis\")\ntoApi = Edge(edge, api)\nreadSessions = Edge(api, sessions, \"SQL\")\nreadCache = Edge(api, cache, \"cache\", \"dashed\")\nvpc = Group(\"Platform VPC\", [api, sessions, cache])","ownership = Architecture([web, ordersApi, ledger, ordersDb, billingJob], [placeOrder, writeOrder, readOrders, postLedger], [clients, ordersRepo, billingRepo], \"lanes\")\nweb = Node(\"Web app\", \"frontend\")\nordersApi = Node(\"Orders API\", \"backend\", \"Node :8080\")\nordersDb = Node(\"orders table\", \"database\", \"Postgres\", null, \"success\")\nbillingJob = Node(\"Nightly billing\", \"backend\", \"cron 02:00\")\nledger = Node(\"Ledger\", \"database\", \"append-only\", null, \"info\")\nplaceOrder = Edge(web, ordersApi, \"POST /orders\")\nwriteOrder = Edge(ordersApi, ordersDb, \"insert\")\nreadOrders = Edge(billingJob, ordersDb, \"read unbilled\", null, \"danger\")\npostLedger = Edge(billingJob, ledger, \"post\")\nclients = Group(\"CLIENTS\", [web], \"plain\")\nordersRepo = Group(\"orders-service\", [ordersApi, ordersDb])\nbillingRepo = Group(\"billing\", [billingJob, ledger])"]},{"name":"Node","group":"Content","signature":"Node(label: string, kind?: \"frontend\" | \"backend\" | \"database\" | \"messagebus\" | \"cloud\" | \"security\" | \"external\", detail?: string, tag?: string, tone?: \"info\" | \"success\" | \"warning\" | \"danger\" | \"strong\", row?: number)","description":"A box in an Architecture. kind sets icon and color (default backend); detail is monospace, up to 2 lines (\\n breaks); tag is a small chip such as \"new\"; tone tints it (danger = risk, strong = where it ends); row pins it to a row (1, 2, ...) in lanes.","tier":"core","pack":"core","examples":[]},{"name":"Edge","group":"Content","signature":"Edge(from: Node, to: Node, label?: string, style?: \"solid\" | \"dashed\" | \"emphasis\" | \"security\", tone?: \"info\" | \"success\" | \"warning\" | \"danger\")","description":"An arrow between two Node statements (pass their names, not strings). style: dashed for async, emphasis for the main path, security for auth or trust flows. tone colors it, e.g. danger for a risky write, success for a read.","tier":"core","pack":"core","examples":[]},{"name":"Group","group":"Content","signature":"Group(label: string, members: Node[], kind?: \"region\" | \"security\" | \"plain\")","description":"A boundary around Node statements (a VPC, a cluster, a trust zone); members still sit where their edges put them. A group whose members are a subset of another's is drawn inside it; kind security draws it red, plain draws only its name.","tier":"core","pack":"core","examples":[]},{"name":"Diff","group":"Content","signature":"Diff(patch: string, title?: string)","description":"Unified diff (git diff output, one or more files) with line numbers. patch is a raw multi-line string. Clicked lines reach the agent as file:+line.","tier":"core","pack":"core","examples":["retryPatch = Diff(\"diff --git a/src/retry.ts b/src/retry.ts\n--- a/src/retry.ts\n+++ b/src/retry.ts\n@@ -10,2 +10,3 @@\n- for (let i = 0; i < 3; i++) {\n+ for (let i = 0; i < MAX_ATTEMPTS; i++) {\n+ if (i > 0) await sleep(backoff(i));\")"]},{"name":"FileTree","group":"Data","signature":"FileTree(entries: string[])","description":"File tree, one path per entry, optionally prefixed with a git status code (A new, M modified, D deleted, R old -> new) and suffixed with \" # note\". Folders are inferred. Clicked files and folders reach the agent by path.","tier":"core","pack":"core","examples":["changedFiles = FileTree([\"M src/session/store.ts # read-through to Postgres\", \"A src/session/pg-store.ts\", \"A migrations/0042_sessions.sql # table + expiry index\", \"R src/session/redis.ts -> src/session/redis-cache.ts\", \"D src/session/legacy.ts\", \"M src/config.ts # SESSIONS_PG flag\"])"]},{"name":"Mermaid","group":"Content","signature":"Mermaid(source: string, caption?: string)","description":"Diagram from Mermaid source (flowchart, sequence, state, class, ER, gantt). source is a raw multi-line string. Keep node labels to a few words; clicked nodes reach the agent by label.","tier":"core","pack":"@austere-axi/pack-mermaid","examples":["requestPath = Mermaid(\"flowchart LR\n client[Client] --> api[API]\n api --> pg[(Postgres)]\", \"Request path\")"]},{"name":"Progress","group":"Data","signature":"Progress(value: number, label?: string, max?: number)","description":"Progress bar. value counts toward max (default 100); label names what is progressing. Shows a percentage.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["migration = Progress(64, \"Rows migrated\")"]},{"name":"Avatar","group":"Data","signature":"Avatar(name: string, src?: string, size?: \"md\" | \"lg\")","description":"Round avatar for a person. Shows the initials of name; src is an optional https image URL.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["owner = Avatar(\"Ada Lovelace\")"]},{"name":"AvatarGroup","group":"Data","signature":"AvatarGroup(avatars: Avatar[], max?: number)","description":"Overlapping Avatars, for reviewers or owners. max (default 4) shows the rest as +N.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["team = AvatarGroup([ada, grace, linus], 2)\nada = Avatar(\"Ada Lovelace\")\ngrace = Avatar(\"Grace Hopper\")\nlinus = Avatar(\"Linus Torvalds\")"]},{"name":"Tooltip","group":"Content","signature":"Tooltip(text: string, tip: string)","description":"Inline text with a short hint on hover or focus (a term and its definition). Keep tip to one line.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["term = Tooltip(\"idempotent\", \"Safe to run twice with the same result.\")"]},{"name":"HoverCard","group":"Content","signature":"HoverCard(text: string, title: string, body?: string)","description":"Inline text that shows a small card (title and a line or two of body) on hover or focus, e.g. a person or a service.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["svc = HoverCard(\"billing-api\", \"billing-api\", \"Owns invoices and refunds. On call: payments team.\")"]},{"name":"Breadcrumb","group":"Content","signature":"Breadcrumb(items: BreadcrumbItem[])","description":"Path trail such as Repo / Package / File, from BreadcrumbItems. Each item is a click target.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["trail = Breadcrumb([repo, pkg, file])\nrepo = BreadcrumbItem(\"austere-axi\")\npkg = BreadcrumbItem(\"packs\")\nfile = BreadcrumbItem(\"shadcn\")"]},{"name":"BreadcrumbItem","group":"Content","signature":"BreadcrumbItem(label: string, href?: string)","description":"One step of a Breadcrumb. href is optional; the last item is the current page.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":[]},{"name":"Kbd","group":"Content","signature":"Kbd(keys: string)","description":"Keyboard shortcut. keys joins keys with \"+\", e.g. \"Ctrl+K\"; each key is drawn as a key cap.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["shortcut = Kbd(\"Ctrl+Shift+P\")"]},{"name":"Skeleton","group":"Content","signature":"Skeleton(lines?: number, shape?: \"lines\" | \"avatar\")","description":"Grey placeholder block for content not yet written or loaded (default 3 lines). shape avatar adds a round head.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["pending = Skeleton(3, \"avatar\")"]},{"name":"Calendar","group":"Data","signature":"Calendar(month: string, highlights?: string[])","description":"Read-only month grid (not a date picker). month is \"YYYY-MM\"; highlights lists \"YYYY-MM-DD\" or \"YYYY-MM-DD label\" entries to mark, e.g. a freeze or a release. Marked days are click targets.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["window = Calendar(\"2026-11\", [\"2026-11-04 Code freeze\", \"2026-11-12 Release\", \"2026-11-13\"])"]},{"name":"Timeline","group":"Content","signature":"Timeline(items: TimelineItem[])","description":"Vertical history or schedule of TimelineItems, oldest first. Each item is a click target.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":["history = Timeline([found, fixed, rollout])\nfound = TimelineItem(\"Bug found\", \"Oct 28\", \"Retries double-charge on timeout.\")\nfixed = TimelineItem(\"Fix merged\", \"Oct 29\", \"Idempotency key added.\", \"current\")\nrollout = TimelineItem(\"Rollout\", \"Nov 3\", \"\", \"upcoming\")"]},{"name":"TimelineItem","group":"Content","signature":"TimelineItem(title: string, date?: string, detail?: string, state?: \"done\" | \"current\" | \"upcoming\")","description":"One event in a Timeline. state: done (default), current or upcoming.","tier":"extended","pack":"@austere-axi/pack-shadcn","examples":[]}]}
|
package/dist/cli.mjs
CHANGED
|
@@ -615,7 +615,7 @@ var init_paths = __esm({
|
|
|
615
615
|
HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
616
616
|
BUNDLED = true;
|
|
617
617
|
ASSET_DIR = BUNDLED ? HERE : path.resolve(HERE, "../../dist");
|
|
618
|
-
VERSION = true ? "0.5.
|
|
618
|
+
VERSION = true ? "0.5.2" : JSON.parse(fs.readFileSync(path.resolve(HERE, "../../package.json"), "utf8")).version;
|
|
619
619
|
CLI_ENTRY = BUNDLED ? fileURLToPath(import.meta.url) : path.resolve(HERE, "main.js");
|
|
620
620
|
securedDir = null;
|
|
621
621
|
}
|
|
@@ -29882,8 +29882,8 @@ WHEN TO USE
|
|
|
29882
29882
|
Plans, comparisons, decisions, reviews, reports: anything easier to grasp as a page.
|
|
29883
29883
|
Not for a few sentences of prose.
|
|
29884
29884
|
|
|
29885
|
-
COMMANDS
|
|
29886
|
-
${BIN2} sessions +
|
|
29885
|
+
COMMANDS (\`${BIN2} <command> --help\` for one command's flags and an example)
|
|
29886
|
+
${BIN2} sessions + command list
|
|
29887
29887
|
${BIN2} <file> open/resume a review [--no-open] [--reopen]
|
|
29888
29888
|
${BIN2} poll <file> long-poll for feedback [--cursor n] [--agent-reply "..."] [--agent-reply-file f|-]
|
|
29889
29889
|
--cursor n acknowledges feedback up to n; --after n returns
|
|
@@ -29924,6 +29924,107 @@ ENV
|
|
|
29924
29924
|
AUSTERE_AXI_IDLE_TIMEOUT_MS (1800000) AUSTERE_AXI_PERSIST=1 AUSTERE_AXI_ALLOWED_HOSTS AUSTERE_AXI_LINK_URL
|
|
29925
29925
|
AUSTERE_AXI_NPM_REGISTRY
|
|
29926
29926
|
`;
|
|
29927
|
+
var COMMANDS = {
|
|
29928
|
+
open: {
|
|
29929
|
+
usage: "<file> [--no-open] [--reopen]",
|
|
29930
|
+
summary: "validate the page and open it for review (`open <file>` is the same)",
|
|
29931
|
+
flags: { "no-open": "do not launch a browser; print the url (and a phone url when Tailscale is up)", reopen: "open a review the user ended or closed again" },
|
|
29932
|
+
example: "plan.html --no-open"
|
|
29933
|
+
},
|
|
29934
|
+
poll: {
|
|
29935
|
+
usage: "poll <file> [--cursor n] [--agent-reply text | --agent-reply-file path|-]",
|
|
29936
|
+
summary: "wait until the reviewer presses Send; returns the feedback batch and a cursor",
|
|
29937
|
+
flags: {
|
|
29938
|
+
cursor: "acknowledge feedback up to n (the cursor the last poll printed)",
|
|
29939
|
+
after: "return everything after n again",
|
|
29940
|
+
"agent-reply": "post a reply first: a small Markdown subset (paragraphs, - lists, `code`, **bold**, links), a line or two",
|
|
29941
|
+
"agent-reply-file": "read the reply from a file, or - for stdin",
|
|
29942
|
+
takeover: "replace a poll that is already listening on this review",
|
|
29943
|
+
"timeout-ms": "return status: timeout after n ms (default: wait for feedback)",
|
|
29944
|
+
owner: "label for this listener, shown to a second poll"
|
|
29945
|
+
},
|
|
29946
|
+
example: 'poll plan.html --cursor 3 --agent-reply "Switched the rollout to dual-write."'
|
|
29947
|
+
},
|
|
29948
|
+
reply: {
|
|
29949
|
+
usage: "reply <file> --agent-reply text | --agent-reply-file path|- [--cursor n]",
|
|
29950
|
+
summary: "post a reply without polling; acknowledges feedback up to the cursor",
|
|
29951
|
+
flags: {
|
|
29952
|
+
"agent-reply": "reply text: a small Markdown subset, a line or two",
|
|
29953
|
+
"agent-reply-file": "read the reply from a file, or - for stdin",
|
|
29954
|
+
cursor: "acknowledge feedback up to n"
|
|
29955
|
+
},
|
|
29956
|
+
example: 'reply plan.html --cursor 3 --agent-reply "Done."'
|
|
29957
|
+
},
|
|
29958
|
+
end: { usage: "end <file>", summary: "stop as the agent; the reviewer can still add notes for later", flags: {}, example: "end plan.html" },
|
|
29959
|
+
close: { usage: "close <file>", summary: "close the review: no more notes until reopen", flags: {}, example: "close plan.html" },
|
|
29960
|
+
reopen: { usage: "reopen <file>", summary: "reopen an ended or closed review", flags: {}, example: "reopen plan.html" },
|
|
29961
|
+
login: {
|
|
29962
|
+
usage: "login [file]",
|
|
29963
|
+
summary: "single-use link that signs a browser in as you (SSH, --no-open, another browser)",
|
|
29964
|
+
flags: {},
|
|
29965
|
+
example: "login plan.html"
|
|
29966
|
+
},
|
|
29967
|
+
feedback: {
|
|
29968
|
+
usage: "feedback <file> [--all] [--peek]",
|
|
29969
|
+
summary: "feedback no agent has answered yet; reading it acknowledges it, reply answers it",
|
|
29970
|
+
flags: { all: "include feedback already answered", peek: "read without acknowledging" },
|
|
29971
|
+
example: "feedback plan.html"
|
|
29972
|
+
},
|
|
29973
|
+
check: {
|
|
29974
|
+
usage: "check <file> [--fix]",
|
|
29975
|
+
summary: "validate the program without a browser: syntax, components, props, references, reachability",
|
|
29976
|
+
flags: { fix: 'declare the packs the page uses (writes the <meta name="austere-packs"> tag)' },
|
|
29977
|
+
example: "check plan.html"
|
|
29978
|
+
},
|
|
29979
|
+
patch: {
|
|
29980
|
+
usage: "patch <file> < statements",
|
|
29981
|
+
summary: "merge statements from stdin: same name replaces, new name adds, `name = null` deletes",
|
|
29982
|
+
flags: {},
|
|
29983
|
+
example: `patch plan.html <<'EOF'
|
|
29984
|
+
intro = Card([CardHeader("New title")])
|
|
29985
|
+
EOF`
|
|
29986
|
+
},
|
|
29987
|
+
spec: {
|
|
29988
|
+
usage: "spec [group|pack...]",
|
|
29989
|
+
summary: "component reference; groups: Layout Content Data Charts Forms Buttons",
|
|
29990
|
+
flags: {},
|
|
29991
|
+
example: "spec Charts Forms"
|
|
29992
|
+
},
|
|
29993
|
+
components: {
|
|
29994
|
+
usage: "components [list [group] | search <words> | show <Name...> | add <pkg|folder|file.tgz> [--trust] | remove <pkg> | new <dir> [--name pkg] | build [dir]]",
|
|
29995
|
+
summary: "every component, including ones spec leaves out; install, remove and write packs",
|
|
29996
|
+
flags: { trust: "install a third-party pack (read its code first)", name: "npm package name for `new`" },
|
|
29997
|
+
example: "components search scatter"
|
|
29998
|
+
},
|
|
29999
|
+
export: {
|
|
30000
|
+
usage: "export <file> [--out path]",
|
|
30001
|
+
summary: "one self-contained HTML file that works offline",
|
|
30002
|
+
flags: { out: "output path (default: <file>.export.html)" },
|
|
30003
|
+
example: "export plan.html --out review.html"
|
|
30004
|
+
},
|
|
30005
|
+
hub: {
|
|
30006
|
+
usage: "hub on|off|status|list|notes|open [words] [--project dir] [--unanswered]",
|
|
30007
|
+
summary: "the owner's home page: every page by project and day, every note",
|
|
30008
|
+
flags: { project: "only pages or notes from this project dir (list, notes)", unanswered: "only notes no agent answered (notes)" },
|
|
30009
|
+
example: "hub notes --unanswered"
|
|
30010
|
+
},
|
|
30011
|
+
share: {
|
|
30012
|
+
usage: 'share <file> --as "<name>" [--auto] | share list [--links] | share revoke <name|id>',
|
|
30013
|
+
summary: "invite link for a teammate on your tailnet; their notes wait for you unless --auto",
|
|
30014
|
+
flags: { as: "the reviewer's name", auto: "send this reviewer's notes straight to the agent", links: "show the links (list)" },
|
|
30015
|
+
example: 'share plan.html --as "Ana"'
|
|
30016
|
+
},
|
|
30017
|
+
stop: { usage: "stop", summary: "stop the background server", flags: {}, example: "stop" },
|
|
30018
|
+
server: {
|
|
30019
|
+
usage: "server [--persist] [--port n] [--verbose]",
|
|
30020
|
+
summary: "run the server in the foreground (under systemd, behind a reverse proxy)",
|
|
30021
|
+
flags: { persist: "never idle out", port: "listen port (default: AUSTERE_AXI_PORT or 4388)", verbose: "log requests", "also-listen": "extra address to listen on (repeatable)" },
|
|
30022
|
+
example: "server --persist"
|
|
30023
|
+
},
|
|
30024
|
+
mcp: { usage: "mcp", summary: "MCP server on stdio: spec check open poll reply patch end as tools", flags: {}, example: "mcp" },
|
|
30025
|
+
help: { usage: "help [command]", summary: "the full workflow, or one command's help", flags: {}, example: "help poll" }
|
|
30026
|
+
};
|
|
30027
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set(["agent-reply", "agent-reply-file", "owner", "out", "port", "also-listen", "timeout-ms", "name", "project", "as", "cursor", "after"]);
|
|
29927
30028
|
function parseArgs(argv) {
|
|
29928
30029
|
const flags = {};
|
|
29929
30030
|
const pos = [];
|
|
@@ -29936,10 +30037,12 @@ function parseArgs(argv) {
|
|
|
29936
30037
|
if (a.startsWith("--")) {
|
|
29937
30038
|
const eq = a.indexOf("=");
|
|
29938
30039
|
const key2 = eq > 0 ? a.slice(2, eq) : a.slice(2);
|
|
29939
|
-
const takesValue = ["agent-reply", "agent-reply-file", "owner", "out", "port", "also-listen", "timeout-ms", "name", "project", "as", "cursor", "after"].includes(key2);
|
|
29940
30040
|
let val = true;
|
|
29941
30041
|
if (eq > 0) val = a.slice(eq + 1);
|
|
29942
|
-
else if (
|
|
30042
|
+
else if (VALUE_FLAGS.has(key2)) {
|
|
30043
|
+
if (i + 1 >= argv.length) return { flags, pos, error: `--${key2} needs a value` };
|
|
30044
|
+
val = argv[++i];
|
|
30045
|
+
}
|
|
29943
30046
|
if (key2 === "also-listen") (flags[key2] ||= []).push(val);
|
|
29944
30047
|
else flags[key2] = val;
|
|
29945
30048
|
} else if (a === "-h") flags.help = true;
|
|
@@ -29952,9 +30055,26 @@ function fail(message, extra = {}) {
|
|
|
29952
30055
|
print({ status: "error", error: message, ...extra });
|
|
29953
30056
|
process.exitCode = 1;
|
|
29954
30057
|
}
|
|
30058
|
+
function usage(message, cmd) {
|
|
30059
|
+
const spec = cmd && COMMANDS[cmd];
|
|
30060
|
+
print({ status: "error", code: "USAGE", error: message, usage: spec ? `${BIN2} ${spec.usage}` : void 0, help: `${BIN2} ${spec ? `${cmd} ` : ""}--help` });
|
|
30061
|
+
process.exitCode = 2;
|
|
30062
|
+
}
|
|
30063
|
+
function commandHelp(cmd) {
|
|
30064
|
+
const spec = COMMANDS[cmd];
|
|
30065
|
+
const lines = [`${BIN2} ${spec.usage}`, ` ${spec.summary}`];
|
|
30066
|
+
const flags = Object.entries(spec.flags);
|
|
30067
|
+
if (flags.length) {
|
|
30068
|
+
lines.push("", "FLAGS");
|
|
30069
|
+
const width = Math.max(...flags.map(([k]) => k.length + (VALUE_FLAGS.has(k) ? 6 : 0)));
|
|
30070
|
+
for (const [k, text] of flags) lines.push(` ${(`--${k}` + (VALUE_FLAGS.has(k) ? " <val>" : "")).padEnd(width + 4)}${text}`);
|
|
30071
|
+
}
|
|
30072
|
+
lines.push("", "EXAMPLE", ` ${BIN2} ${spec.example}`, "", `Full workflow and file skeleton: ${BIN2} --help`);
|
|
30073
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
30074
|
+
}
|
|
29955
30075
|
function needFile(file3, cmd) {
|
|
29956
30076
|
if (!file3) {
|
|
29957
|
-
|
|
30077
|
+
usage(`${cmd} needs a file: ${BIN2} ${cmd} <file.html>`, cmd);
|
|
29958
30078
|
return null;
|
|
29959
30079
|
}
|
|
29960
30080
|
const abs = canonicalFile(file3);
|
|
@@ -29992,16 +30112,24 @@ async function cmdHome() {
|
|
|
29992
30112
|
let sessions = [];
|
|
29993
30113
|
if (h) {
|
|
29994
30114
|
const r = await request("GET", "/api/sessions");
|
|
29995
|
-
sessions = (r.data.sessions || []).filter((s) => s.status !== "ended")
|
|
29996
|
-
|
|
29997
|
-
|
|
29998
|
-
|
|
29999
|
-
|
|
30000
|
-
|
|
30001
|
-
|
|
30002
|
-
|
|
30003
|
-
|
|
30004
|
-
print({
|
|
30115
|
+
sessions = (r.data.sessions || []).filter((s) => s.status !== "ended");
|
|
30116
|
+
}
|
|
30117
|
+
const shown = sessions.slice(0, 12).map((s) => ({
|
|
30118
|
+
file: s.file,
|
|
30119
|
+
presence: s.presence,
|
|
30120
|
+
browsers: s.browsers,
|
|
30121
|
+
pending: s.pending || void 0,
|
|
30122
|
+
url: s.links.local
|
|
30123
|
+
}));
|
|
30124
|
+
print({
|
|
30125
|
+
bin: `${BIN2} ${VERSION}`,
|
|
30126
|
+
description: "review pages written in OpenUI Lang; the reviewer annotates them in the browser and notes come back by statement name",
|
|
30127
|
+
server: h ? `running on ${port()} (v${h.version})` : "not running",
|
|
30128
|
+
open_sessions: sessions.length > shown.length ? `${shown.length} of ${sessions.length} shown` : sessions.length,
|
|
30129
|
+
sessions: shown.length ? shown : void 0,
|
|
30130
|
+
commands: Object.fromEntries(Object.entries(COMMANDS).map(([name, c]) => [name === "open" ? "<file>" : name, c.summary])),
|
|
30131
|
+
next: shown.length ? `${BIN2} poll <file> waits for feedback on an open session. ${BIN2} --help: workflow and file skeleton.` : `${BIN2} --help: workflow and file skeleton. ${BIN2} spec: component reference. ${BIN2} <command> --help: one command.`
|
|
30132
|
+
});
|
|
30005
30133
|
}
|
|
30006
30134
|
async function cmdOpen(file3, flags) {
|
|
30007
30135
|
const abs = needFile(file3, "open");
|
|
@@ -30140,7 +30268,7 @@ async function cmdReply(file3, flags) {
|
|
|
30140
30268
|
const abs = needFile(file3, "reply");
|
|
30141
30269
|
if (!abs) return;
|
|
30142
30270
|
const text = await replyText(flags);
|
|
30143
|
-
if (!text) return
|
|
30271
|
+
if (!text) return usage('reply needs text: --agent-reply "..." or --agent-reply-file <path|->', "reply");
|
|
30144
30272
|
await ensureServer();
|
|
30145
30273
|
const r = await request("POST", "/api/reply", { file: abs, text, cursor: seqFlag(flags, "cursor") }, { timeoutMs: 1e4 });
|
|
30146
30274
|
if (r.status !== 200) return fail(r.data?.error || `reply failed (${r.status})`);
|
|
@@ -30205,7 +30333,7 @@ async function cmdCheck(file3, flags = {}) {
|
|
|
30205
30333
|
async function cmdPatch(file3) {
|
|
30206
30334
|
const abs = needFile(file3, "patch");
|
|
30207
30335
|
if (!abs) return;
|
|
30208
|
-
if (process.stdin.isTTY) return
|
|
30336
|
+
if (process.stdin.isTTY) return usage(`pipe the changed statements on stdin: ${BIN2} patch ${quote(file3)} <<'EOF' ... EOF`, "patch");
|
|
30209
30337
|
const patch = await readStdin();
|
|
30210
30338
|
if (!patch.trim()) return fail("stdin was empty");
|
|
30211
30339
|
const html = fs14.readFileSync(abs, "utf8");
|
|
@@ -30253,7 +30381,7 @@ More components (\`${BIN2} spec <pack>\` for signatures). A page using one must
|
|
|
30253
30381
|
const parts = text.split(/\n(?=### )/);
|
|
30254
30382
|
const head = parts[0].split("\n## Component Signatures")[0];
|
|
30255
30383
|
const picked = parts.filter((p) => p.startsWith("### ") && wanted.has(p.slice(4, p.indexOf("\n")).trim().toLowerCase()));
|
|
30256
|
-
if (!picked.length) return
|
|
30384
|
+
if (!picked.length) return usage(`unknown group; one of: Layout Content Data Charts Forms Buttons, or an installed pack`, "spec");
|
|
30257
30385
|
const trimmed = picked.map((p) => p.split(/\n## /)[0]);
|
|
30258
30386
|
process.stdout.write(`${head}
|
|
30259
30387
|
|
|
@@ -30284,7 +30412,7 @@ async function cmdComponents(sub, args, flags) {
|
|
|
30284
30412
|
case "show":
|
|
30285
30413
|
return printResult(showComponents(args));
|
|
30286
30414
|
case "add": {
|
|
30287
|
-
if (!args[0]) return
|
|
30415
|
+
if (!args[0]) return usage(`add needs a pack: ${BIN2} components add <npm-package>[@version] | <folder> | <file.tgz>`, "components");
|
|
30288
30416
|
const { addPack: addPack2 } = await Promise.resolve().then(() => (init_install(), install_exports));
|
|
30289
30417
|
let r;
|
|
30290
30418
|
try {
|
|
@@ -30307,7 +30435,7 @@ async function cmdComponents(sub, args, flags) {
|
|
|
30307
30435
|
});
|
|
30308
30436
|
}
|
|
30309
30437
|
case "remove": {
|
|
30310
|
-
if (!args[0]) return
|
|
30438
|
+
if (!args[0]) return usage(`remove needs a pack name: ${BIN2} components remove <name>`, "components");
|
|
30311
30439
|
const { removePack: removePack2 } = await Promise.resolve().then(() => (init_install(), install_exports));
|
|
30312
30440
|
const r = removePack2(args[0]);
|
|
30313
30441
|
if (!r) return fail(`${args[0]} is not installed (${BIN2} components list)`);
|
|
@@ -30352,7 +30480,7 @@ async function cmdComponents(sub, args, flags) {
|
|
|
30352
30480
|
default: {
|
|
30353
30481
|
const listed = listComponents(sub);
|
|
30354
30482
|
if (listed.status !== "error") return print(listed);
|
|
30355
|
-
return
|
|
30483
|
+
return usage(`unknown components command: ${sub}. One of: list search show add remove new build`, "components");
|
|
30356
30484
|
}
|
|
30357
30485
|
}
|
|
30358
30486
|
}
|
|
@@ -30514,7 +30642,7 @@ async function cmdHub(sub, args, flags) {
|
|
|
30514
30642
|
return print({ status: opened ? "opened" : "open the url", url: url2, sign_in: opened ? void 0 : signInHint() });
|
|
30515
30643
|
}
|
|
30516
30644
|
default:
|
|
30517
|
-
return
|
|
30645
|
+
return usage(`unknown hub command: ${sub}. One of: on off status list notes open`, "hub");
|
|
30518
30646
|
}
|
|
30519
30647
|
}
|
|
30520
30648
|
function ago(ms) {
|
|
@@ -30547,7 +30675,7 @@ async function cmdShare(args, flags) {
|
|
|
30547
30675
|
}
|
|
30548
30676
|
if (sub === "revoke") {
|
|
30549
30677
|
const key2 = more.join(" ");
|
|
30550
|
-
if (!key2) return
|
|
30678
|
+
if (!key2) return usage(`revoke needs a name or id: ${BIN2} share revoke <name|id> (see ${BIN2} share list)`, "share");
|
|
30551
30679
|
let revoked;
|
|
30552
30680
|
if (await serverIfRunning()) {
|
|
30553
30681
|
const r2 = await request("POST", "/api/share/revoke", { key: key2 });
|
|
@@ -30561,7 +30689,7 @@ async function cmdShare(args, flags) {
|
|
|
30561
30689
|
}
|
|
30562
30690
|
const abs = needFile(sub, "share");
|
|
30563
30691
|
if (!abs) return;
|
|
30564
|
-
if (typeof flags.as !== "string" || !flags.as.trim()) return
|
|
30692
|
+
if (typeof flags.as !== "string" || !flags.as.trim()) return usage(`share needs a reviewer name: ${BIN2} share ${quote(sub)} --as "<name>"`, "share");
|
|
30565
30693
|
await ensureServer();
|
|
30566
30694
|
const r = await request("POST", "/api/share", { file: abs, name: flags.as, auto: !!flags.auto });
|
|
30567
30695
|
if (r.status !== 200) return fail(r.data?.error || `share failed (${r.status})`);
|
|
@@ -30618,18 +30746,23 @@ async function main() {
|
|
|
30618
30746
|
if (major < MIN_NODE[0] || major === MIN_NODE[0] && minor < MIN_NODE[1]) {
|
|
30619
30747
|
return fail(`austere-axi needs Node ${MIN_NODE.join(".")} or newer; this is ${process.versions.node}. Install a current Node LTS.`);
|
|
30620
30748
|
}
|
|
30621
|
-
const { flags, pos } = parseArgs(process.argv.slice(2));
|
|
30749
|
+
const { flags, pos, error: error62 } = parseArgs(process.argv.slice(2));
|
|
30622
30750
|
if (flags.version) return process.stdout.write(VERSION + "\n");
|
|
30623
30751
|
const [cmd, ...rest] = pos;
|
|
30624
|
-
|
|
30625
|
-
|
|
30626
|
-
|
|
30627
|
-
|
|
30628
|
-
|
|
30629
|
-
`
|
|
30630
|
-
|
|
30631
|
-
|
|
30632
|
-
|
|
30752
|
+
let name = null;
|
|
30753
|
+
if (cmd !== void 0) {
|
|
30754
|
+
if (Object.hasOwn(COMMANDS, cmd)) name = cmd;
|
|
30755
|
+
else if (/\.html?$/i.test(cmd) || fs14.existsSync(cmd)) name = "open";
|
|
30756
|
+
else if (flags.help) return process.stdout.write(HELP);
|
|
30757
|
+
else return usage(`unknown command: ${cmd}. One of: ${Object.keys(COMMANDS).join(" ")}, or a page file`);
|
|
30758
|
+
}
|
|
30759
|
+
if (flags.help) return name && name !== "help" ? commandHelp(name) : process.stdout.write(HELP);
|
|
30760
|
+
if (error62) return usage(error62, name);
|
|
30761
|
+
const allowed = name ? Object.keys(COMMANDS[name].flags) : [];
|
|
30762
|
+
const unknown2 = Object.keys(flags).filter((k) => !allowed.includes(k));
|
|
30763
|
+
if (unknown2.length) {
|
|
30764
|
+
const valid = allowed.length ? `valid: ${allowed.map((k) => `--${k}`).join(" ")}` : "it takes no flags";
|
|
30765
|
+
return usage(`unknown flag${unknown2.length > 1 ? "s" : ""} for ${name ?? BIN2}: ${unknown2.map((k) => `--${k}`).join(" ")}; ${valid}`, name);
|
|
30633
30766
|
}
|
|
30634
30767
|
stateDir();
|
|
30635
30768
|
switch (cmd) {
|
|
@@ -30674,10 +30807,11 @@ Replies render a small Markdown subset (paragraphs, - lists, \`code\`, **bold**,
|
|
|
30674
30807
|
case "open":
|
|
30675
30808
|
return cmdOpen(rest[0], flags);
|
|
30676
30809
|
case "help":
|
|
30677
|
-
return process.stdout.write(HELP);
|
|
30810
|
+
if (!rest[0]) return process.stdout.write(HELP);
|
|
30811
|
+
if (!Object.hasOwn(COMMANDS, rest[0])) return usage(`no command named ${rest[0]}. One of: ${Object.keys(COMMANDS).join(" ")}`, "help");
|
|
30812
|
+
return commandHelp(rest[0]);
|
|
30678
30813
|
default:
|
|
30679
|
-
|
|
30680
|
-
return fail(`unknown command: ${cmd}. Run ${BIN2} --help`);
|
|
30814
|
+
return cmdOpen(cmd, flags);
|
|
30681
30815
|
}
|
|
30682
30816
|
}
|
|
30683
30817
|
main().catch((err) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": 1,
|
|
3
3
|
"pack": "@austere-axi/pack-mermaid",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.2",
|
|
5
5
|
"groups": [
|
|
6
6
|
{
|
|
7
7
|
"name": "Content",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
}
|
|
30
30
|
],
|
|
31
31
|
"api": 1,
|
|
32
|
-
"integrity": "sha384
|
|
32
|
+
"integrity": "sha384-1+XBvdGl+fWIMBvzXkUrVl/h2RE3F+O85RZUmqm5BFRdGv/ZvTaU9MOpGIxNmHRu",
|
|
33
33
|
"size": 5782,
|
|
34
34
|
"css": true,
|
|
35
35
|
"defs": {
|
|
@@ -22,4 +22,4 @@
|
|
|
22
22
|
font-size: 12.5px;
|
|
23
23
|
color: var(--austere-muted);
|
|
24
24
|
}
|
|
25
|
-
`;var s={components:[N],css:V};var $=l(w());(0,$.registerPack)({name:"@austere-axi/pack-mermaid",version:"0.5.
|
|
25
|
+
`;var s={components:[N],css:V};var $=l(w());(0,$.registerPack)({name:"@austere-axi/pack-mermaid",version:"0.5.2",api:1,components:[].concat(s&&s.components?s.components:s),css:s&&s.css});})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": 1,
|
|
3
3
|
"pack": "@austere-axi/pack-shadcn",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.2",
|
|
5
5
|
"groups": [
|
|
6
6
|
{
|
|
7
7
|
"name": "Data",
|
|
@@ -195,7 +195,7 @@
|
|
|
195
195
|
}
|
|
196
196
|
],
|
|
197
197
|
"api": 1,
|
|
198
|
-
"integrity": "sha384-
|
|
198
|
+
"integrity": "sha384-DyzR2GIcDb2W7YXtHpIpAZRP2LbKJQXroF7POadUdFe1rMT1SWWn8nBbli2ty0R0",
|
|
199
199
|
"size": 16313,
|
|
200
200
|
"css": true,
|
|
201
201
|
"defs": {
|
|
@@ -66,4 +66,4 @@ rollout = TimelineItem("Rollout", "Nov 3", "", "upcoming")`});var ue=`.sh-muted
|
|
|
66
66
|
.sh-timeline-item.is-upcoming .sh-timeline-dot { background: transparent; border: 1px solid var(--austere-muted); }
|
|
67
67
|
.sh-timeline-body { min-width: 0; font-size: 13.5px; overflow-wrap: anywhere; }
|
|
68
68
|
.sh-timeline-head { display: flex; flex-wrap: wrap; gap: 4px 12px; }
|
|
69
|
-
`;var y={components:[X,M,ae,re,te,oe,H,ne,pe,de,ce,_],css:ue};var he=r(l());(0,he.registerPack)({name:"@austere-axi/pack-shadcn",version:"0.5.
|
|
69
|
+
`;var y={components:[X,M,ae,re,te,oe,H,ne,pe,de,ce,_],css:ue};var he=r(l());(0,he.registerPack)({name:"@austere-axi/pack-shadcn",version:"0.5.2",api:1,components:[].concat(y&&y.components?y.components:y),css:y&&y.css});})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "austere-axi",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Agent-authored review artifacts in OpenUI Lang: a few hundred tokens instead of a whole HTML page, with statement-level annotations fed back to the agent.",
|
|
5
5
|
"mcpName": "io.github.MandalorianBatman/austere-axi",
|
|
6
6
|
"type": "module",
|