@augmentcode/auggie 0.37.0-prerelease.3 → 1.2.0-prerelease.202608251328

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.
@@ -0,0 +1,21 @@
1
+ import{Container as bi,Text as Te}from"@earendil-works/pi-tui";import{getKeybindings as $n}from"@earendil-works/pi-tui";import{getMarkdownTheme as yn}from"@augmentcode/auggie-v2";import{Input as vt}from"@earendil-works/pi-tui";function O(n){return{apply:(e,t)=>n.component.setProps(n.select(e,t)),invalidate:()=>n.component.invalidate()}}function U(n){return{apply:(e,t)=>{n.predicate&&!n.predicate(e,t)||n.resolve(t.tab)?.setProps(n.select(e,t))}}}import{visibleWidth as Ie,wrapTextWithAnsi as Se}from"@earendil-works/pi-tui";var Q=" (Recommended)",$e=Ie(Q),E=class n{static ACTIVE_POINTER="\u276F ";static INACTIVE_POINTER=" ";static NUMBER_SEPARATOR=". ";static INPUT_CURSOR_START="\x1B[7m";static INPUT_CURSOR_END="\x1B[27m";static SEGMENTER=new Intl.Segmenter;static CONFIRMED_MARK=" \u2714";static MIN_CONTENT_WIDTH=1;items;maxVisible;theme;numberStartOffset;totalItemsForNumbering;selectedIndex=0;focused=!0;inputBuffer="";inputCursor=0;confirmedIndex=void 0;confirmedLabelOverride=void 0;constructor(e,t,i,o={}){this.items=e,this.maxVisible=Math.max(1,t),this.theme=i,this.numberStartOffset=o.numberStartOffset??0,this.totalItemsForNumbering=o.totalItemsForNumbering??e.length}setNumbering(e,t){this.numberStartOffset=e,this.totalItemsForNumbering=Math.max(1,t)}setSelectedIndex(e){this.selectedIndex=Math.max(0,Math.min(e,this.items.length-1))}setFocused(e){this.focused=e}setConfirmedIndex(e,t){if(e===void 0){this.confirmedIndex=void 0,this.confirmedLabelOverride=void 0;return}this.confirmedIndex=Math.max(0,Math.min(e,this.items.length-1)),this.confirmedLabelOverride=t}setInputBuffer(e){this.inputBuffer=e,this.inputCursor>e.length&&(this.inputCursor=e.length)}setInputCursor(e){this.inputCursor=Math.max(0,Math.min(e,this.inputBuffer.length))}handleInput(e){}invalidate(){}render(e){if(this.items.length===0)return[];let{startIndex:t,endIndex:i}=this.computeVisibleWindow(),o=String(Math.max(1,this.totalItemsForNumbering)).length,r=[];for(let s=t;s<i;s++){let a=this.items[s];if(!a)continue;let u=s===this.selectedIndex&&this.focused;r.push(...this.renderItem(a,s,u,e,o))}return this.hasItemsOutsideWindow(t,i)&&r.push(this.theme.scrollInfo(` (${this.selectedIndex+1}/${this.items.length})`)),r}computeVisibleWindow(){let e=Math.floor(this.maxVisible/2),t=Math.max(0,Math.min(this.selectedIndex-e,this.items.length-this.maxVisible)),i=Math.min(t+this.maxVisible,this.items.length);return{startIndex:t,endIndex:i}}hasItemsOutsideWindow(e,t){return e>0||t<this.items.length}renderItem(e,t,i,o,r){let s=this.buildRowPrefix(t,i,r),a=" ".repeat(Ie(s)),u=Math.max(n.MIN_CONTENT_WIDTH,o-Ie(s));if(this.shouldRenderAsInlineInput(e,i))return this.renderInlineInputRow(s,a,u);let l=t===this.confirmedIndex,p=e.kind==="option"&&e.recommended===!0?Q:"",d=l?this.confirmedLabelOverride??`${e.label}${p}`:`${e.label}${p}`,m=l?`${d}${n.CONFIRMED_MARK}`:d,f=i||l;return[...this.renderLabelBlock(m,s,a,u,f),...this.renderDescriptionBlock(e.description,a,u)]}buildRowPrefix(e,t,i){let o=t?n.ACTIVE_POINTER:n.INACTIVE_POINTER,r=this.numberStartOffset+e+1,s=String(r).padStart(i," ");return`${o}${s}${n.NUMBER_SEPARATOR}`}shouldRenderAsInlineInput(e,t){return e.kind==="other"&&t}renderInlineInputRow(e,t,i){let o=Math.max(0,Math.min(this.inputCursor,this.inputBuffer.length)),r=this.inputBuffer.slice(0,o),s=this.inputBuffer.slice(o),u=n.SEGMENTER.segment(s)[Symbol.iterator]().next().value?.segment??" ",l=s.slice(u.length),p=`${r}${n.INPUT_CURSOR_START}${u}${n.INPUT_CURSOR_END}${l}`;return Se(p,i).map((m,f)=>{let x=f===0?e:t;return this.theme.selectedText(`${x}${m}`)})}renderLabelBlock(e,t,i,o,r){return Se(e,o).map((a,u)=>{let p=`${u===0?t:i}${a}`;return r?this.theme.selectedText(p):p})}renderDescriptionBlock(e,t,i){return e?Se(e,i).map(r=>`${t}${this.theme.description(r)}`):[]}};var G=class{select;constructor(e){this.select=new E([e.item],1,e.theme,{numberStartOffset:0,totalItemsForNumbering:1})}setProps(e){this.select.setFocused(e.focused),this.select.setNumbering(e.numbering.offset,e.numbering.total)}handleInput(e){}invalidate(){this.select.invalidate()}render(e){return this.select.render(e)}};import{truncateToWidth as K,visibleWidth as Ae,wrapTextWithAnsi as Ue}from"@earendil-works/pi-tui";var je=["other","chat","next"],c={option:{label:"",reserved:!1,livesInMainList:!0,numbered:!0,activatesInputMode:!1,blocksMultiToggle:!1,autoSubmitsInMulti:!1,autoAppendOnSingleSelectNoPreview:!1,autoAppendOnMultiSelect:!1},other:{label:"Type something.",reserved:!0,livesInMainList:!0,numbered:!0,activatesInputMode:!0,blocksMultiToggle:!1,autoSubmitsInMulti:!1,autoAppendOnSingleSelectNoPreview:!0,autoAppendOnMultiSelect:!1},chat:{label:"Chat about this",reserved:!0,livesInMainList:!1,numbered:!0,activatesInputMode:!1,blocksMultiToggle:!1,autoSubmitsInMulti:!1,autoAppendOnSingleSelectNoPreview:!1,autoAppendOnMultiSelect:!1},next:{label:"Next",reserved:!0,livesInMainList:!0,numbered:!1,activatesInputMode:!1,blocksMultiToggle:!0,autoSubmitsInMulti:!0,autoAppendOnSingleSelectNoPreview:!1,autoAppendOnMultiSelect:!0}},Wt={other:c.other.label,chat:c.chat.label,next:c.next.label},Ri=new Set(["Other",...je.filter(n=>c[n].reserved).map(n=>c[n].label)]);function Fe(n,e){let t=[];for(let i of je){let o=c[i];o.livesInMainList&&(n.multiSelect===!0?o.autoAppendOnMultiSelect&&t.push(i):o.autoAppendOnSingleSelectNoPreview&&!e&&t.push(i))}return t}var Ge="\u276F ",_e=" ",Vt="[\u2714]",Ke="[ ]",Xe=". ",Ye=" ",Ht=" ",Ze="Submit",X=class{props;theme;question;constructor(e,t){this.theme=e,this.question=t,this.props={rows:[],nextActive:!1,nextLabel:c.next.label}}setProps(e){this.props=e}handleInput(e){}invalidate(){}render(e){let t=[],i=this.prefixVisibleWidth(),o=Math.max(1,e-i),r=String(Math.max(1,this.question.options.length)).length;for(let u=0;u<this.question.options.length;u++){let l=this.question.options[u],p=this.props.rows[u];if(!l||!p)continue;let d=p.active?this.theme.fg("accent",Ge):_e,m=p.checked?this.theme.fg("accent",Vt):this.theme.fg("muted",Ke),f=l.recommended===!0?`${K(l.label,Math.max(1,o-Ae(Q)),"\u2026")}${Q}`:K(l.label,o,"\u2026"),x=p.active?this.theme.fg("accent",this.theme.bold(f)):f,_=String(u+1).padStart(r," "),F=`${d}${_}${Xe}${m}${Ye}${x}`;if(t.push(K(F,e,"")),l.description){let N=Ue(l.description,o);for(let xe of N)t.push(Ht+this.theme.fg("muted",xe))}}let s=this.props.nextActive?this.theme.fg("accent",Ge):_e,a=this.props.nextActive?this.theme.fg("accent",this.theme.bold(this.props.nextLabel)):this.props.nextLabel;return t.push(K(`${s}${a}`,e,"")),t}naturalHeight(e){let t=Math.max(1,e-this.prefixVisibleWidth()),i=0;for(let o of this.question.options)o&&(i+=1,o.description&&(i+=Ue(o.description,t).length));return i+1}prefixVisibleWidth(){let e=String(Math.max(1,this.question.options.length)).length;return Ae(_e)+e+Ae(`${Xe}${Ke}${Ye}`)}};var $t=10,Y=class{select;constructor(e){this.select=new E(e.items,Math.min(e.items.length,$t),e.theme,{numberStartOffset:0,totalItemsForNumbering:e.items.length+1})}setProps(e){this.select.setSelectedIndex(e.selectedIndex),this.select.setFocused(e.focused),this.select.setConfirmedIndex(e.confirmed?.index,e.confirmed?.labelOverride),this.select.setInputBuffer(e.inputBuffer),this.select.setInputCursor(e.inputCursor)}handleInput(e){}invalidate(){this.select.invalidate()}render(e){return this.select.render(e)}};import{Markdown as Xt,visibleWidth as Yt}from"@earendil-works/pi-tui";import{truncateToWidth as jt,visibleWidth as Ft}from"@earendil-works/pi-tui";var Ut=new RegExp("\\x1b\\[[0-9;]*m","g"),Gt=new RegExp("\\x1b\\]8;[^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)","g"),Kt=/^`{3}/,D=2,T=2,g=1,ze=40;function Ee(n){return n.filter(e=>{let t=e.replace(Ut,"").replace(Gt,"");return!Kt.test(t)})}function Pe(n,e,t,i=0){let o=Math.max(1,e-T),r=Math.max(1,o-2*g),s=" ".repeat(g),u=[t(`\u250C${"\u2500".repeat(o)}\u2510`)];for(let l of n){let p=jt(l,r,"",!0);u.push(`${t("\u2502")}${s}${p}${s}${t("\u2502")}`)}if(i>0){let l=` \u2702 \u2500\u2500 ${i} lines hidden \u2500\u2500 `,p=o-l.length,d="\u2500".repeat(Math.max(0,Math.floor(p/2))),m="\u2500".repeat(Math.max(0,o-d.length-l.length));u.push(t(`\u2514${d}${l}${m}\u2518`))}else u.push(t(`\u2514${"\u2500".repeat(o)}\u2518`));return u}function Je(n,e){let t=Math.min(ze,e);for(let r of n){let s=Ft(r.replace(/\s+$/,""));s>t&&(t=s)}let i=Math.min(t,e),o=i+T+2*g;return{innerWidth:i,boxWidth:o}}var z=20,J=15,et="No preview available",L=2,Z=class{previewTexts;markdownCache;cachedWidth;theme;markdownTheme;constructor(e,t,i){this.theme=t,this.markdownTheme=i,this.previewTexts=new Map;for(let o=0;o<e.options.length;o++){let r=e.options[o]?.preview;r&&r.length>0&&this.previewTexts.set(o,r)}this.markdownCache=new Map}hasAnyPreview(){return this.previewTexts.size>0}has(e){return this.previewTexts.has(e)}bodyFor(e,t){if(this.cachedWidth!==t){for(let r of this.markdownCache.values())r.invalidate();this.cachedWidth=t}let i=this.previewTexts.get(e);if(!i){let r=this.theme.fg("dim",et),s=Math.max(0,t-Yt(r));return[r+" ".repeat(s)]}let o=this.markdownCache.get(e);return o||(o=new Xt(i,0,0,this.markdownTheme),this.markdownCache.set(e,o)),Ee(o.render(t))}invalidate(){for(let e of this.markdownCache.values())e.invalidate();this.cachedWidth=void 0}};var tt="Notes: press n to add notes",q=class{theme;cache;constructor(e){this.theme=e.theme,this.cache=new Z(e.question,e.theme,e.markdownTheme)}hasAnyPreview(){return this.cache.hasAnyPreview()}has(e){return this.cache.has(e)}invalidate(){this.cache.invalidate()}blockHeight(e,t,i){let r=Math.max(1,(i==="side-by-side"?z:J)-D-L),s=Math.max(1,e-T-2*g),a=this.cache.bodyFor(t,s).length,u=Math.min(a,r);return D+u+L}renderBlock(e,t,i,o,r){let a=Math.max(1,(i==="side-by-side"?z:J)-D-L),u=Math.max(1,e-T-2*g),l=this.cache.bodyFor(t,u),p=l.length>a,d=p?l.length-a:0,m=p?l.slice(0,a):l,{boxWidth:f}=Je(m,u),_=Pe(m,f,xe=>this.theme.fg("accent",xe),d),N=o&&!r&&this.cache.has(t)?this.theme.fg("muted",tt):"";return[..._,"",N]}};import{visibleWidth as nt}from"@earendil-works/pi-tui";var Re=100,P=2,R=1,W=1,ee=30,Zt=.5,Ce=45,zt=2;function te(n,e){return n>=Re&&e>=Re?"side-by-side":"stacked"}function Jt(n,e,t){let i=String(Math.max(1,e)).length+4,o=zt,r=0;for(let l of n){let p=l.kind==="option"&&l.recommended===!0?$e:0,d=nt(l.label)+p;d>r&&(r=d)}let s=r+i+o,a=Math.min(s,Math.floor(t*Zt)),u=t-P-Ce;return Math.max(ee,Math.min(a,Math.max(1,u)))}function en(n,e,t){let i=ee;for(let o=0;o<n.length;o++){let r=e[o]??[],s=n[o]?.multiSelect?r.length:r.length+1,a=Jt(r,s,t);a>i&&(i=a)}return i}function tn(n){let e=0;for(let t of n.options){let i=t.preview;if(i)for(let o of i.split(`
2
+ `)){let r=nt(o);r>e&&(e=r)}}return e}function nn(n,e){let t=Ce;for(let i of n){let o=tn(i),s=Math.min(o,e-P-ee)+T+2*g+R;s>t&&(t=s)}return t}function it(n,e,t,i){let o=en(n,e,i);if(o<=ee)return o;let r=nn(t,i),s=i-P-r,a=i-P-Ce;return Math.min(Math.max(o,s),Math.max(1,a))}function ke(n,e){let t=P,i=Math.min(e,Math.max(1,n-t-1)),o=Math.max(1,n-i-t);return{leftWidth:i,rightWidth:o,gap:t}}function Be(n,e,t){if(e==="stacked")return{optionsWidth:n,previewWidth:n};let{leftWidth:i,rightWidth:o}=ke(n,t);return{optionsWidth:i,previewWidth:Math.max(1,o-R)}}import{truncateToWidth as ot,visibleWidth as on}from"@earendil-works/pi-tui";var ne=class{question;getTerminalWidth;optionListView;previewBlock;props;globalLeftWidth=()=>{throw new Error("PreviewPane.setGlobalLeftWidth must be called before render()")};constructor(e){this.question=e.question,this.getTerminalWidth=e.getTerminalWidth,this.optionListView=e.optionListView,this.previewBlock=e.previewBlock,this.props={notesVisible:!1,selectedIndex:0,focused:!1}}setGlobalLeftWidth(e){this.globalLeftWidth=e}getAdaptiveLeft(e){return this.globalLeftWidth(e)}setProps(e){this.props=e}handleInput(e){}invalidate(){this.previewBlock.invalidate(),this.optionListView.invalidate()}render(e){if(this.question.multiSelect===!0)return this.optionListView.render(e);if(!this.previewBlock.hasAnyPreview())return this.optionListView.render(e);let t=te(this.getTerminalWidth(),e);return t==="side-by-side"?this.renderSideBySide(e,t):[...this.optionListView.render(e),...new Array(W).fill(""),...this.previewBlock.renderBlock(e,this.props.selectedIndex,t,this.props.focused,this.props.notesVisible)]}naturalHeight(e){if(this.question.multiSelect===!0)return this.optionListView.render(e).length;if(!this.previewBlock.hasAnyPreview())return this.optionListView.render(e).length;let t=te(this.getTerminalWidth(),e),i=this.getAdaptiveLeft(e),{optionsWidth:o,previewWidth:r}=Be(e,t,i),s=this.optionListView.render(o).length,a=this.previewBlock.blockHeight(r,this.props.selectedIndex,t);return t==="side-by-side"?Math.max(s,a):s+W+a}maxNaturalHeight(e){if(this.question.multiSelect===!0)return this.optionListView.render(e).length;if(!this.previewBlock.hasAnyPreview())return this.optionListView.render(e).length;let t=te(this.getTerminalWidth(),e),i=this.getAdaptiveLeft(e),{optionsWidth:o,previewWidth:r}=Be(e,t,i),s=this.optionListView.render(o).length,a=0;for(let u=0;u<this.question.options.length;u++){let l=this.previewBlock.blockHeight(r,u,t);l>a&&(a=l)}return t==="side-by-side"?Math.max(s,a):s+W+a}renderSideBySide(e,t){let i=this.getAdaptiveLeft(e),{leftWidth:o,rightWidth:r,gap:s}=ke(e,i),a=this.optionListView.render(o),u=this.renderPaddedPreviewLines(r,t),l=Math.max(a.length,u.length),p=" ".repeat(s),d=[];for(let m=0;m<l;m++){let f=a[m]??"",x=u[m]??"",_=ot(f,o,""),F=" ".repeat(Math.max(0,o-on(_))),N=`${_}${F}${p}${x}`;d.push(ot(N,e,""))}return d}renderPaddedPreviewLines(e,t){let i=Math.max(1,e-R),o=this.previewBlock.renderBlock(i,this.props.selectedIndex,t,this.props.focused,this.props.notesVisible),r=" ".repeat(R);return o.map(s=>s===""?"":`${r}${s}`)}};import{truncateToWidth as rn}from"@earendil-works/pi-tui";var sn="\u276F ",an=" ",un=". ",ln="Submit answers",pn="Cancel",ie=class{props;theme;constructor(e){this.theme=e,this.props={rows:[{active:!1},{active:!1}]}}setProps(e){this.props=e}handleInput(e){}invalidate(){}naturalHeight(e){return 2}render(e){let t=[];for(let i=0;i<2;i++){let o=i===0?ln:pn,r=this.props.rows[i]?.active??!1,s=r?sn:an,a=`${i+1}${un}`,u=r?this.theme.fg("accent",this.theme.bold(o)):this.theme.fg("text",o);t.push(rn(`${s}${a}${u}`,e,""))}return t}};import{truncateToWidth as cn}from"@earendil-works/pi-tui";var oe=class{props;theme;constructor(e){this.theme=e,this.props={tabs:[],submit:{active:!1,allAnswered:!1}}}setProps(e){this.props=e}handleInput(e){}invalidate(){}render(e){let t=[" \u2190 "];for(let s of this.props.tabs){let u=` ${s.answered?"\u25A0":"\u25A1"} ${s.label} `,l=s.active?this.theme.bg("selectedBg",this.theme.fg("text",u)):this.theme.fg(s.answered?"success":"muted",u);t.push(l),t.push(" ")}let i=" \u2713 Submit ",o=this.props.submit.active?this.theme.bg("selectedBg",this.theme.fg("text",i)):this.theme.fg(this.props.submit.allAnswered?"success":"dim",i);return t.push(o),t.push(" \u2192"),[cn(t.join(""),e,""),""]}};import{DynamicBorder as gn}from"@augmentcode/auggie-v2";import{Container as wn,Spacer as ut}from"@earendil-works/pi-tui";var re=class{getMax;getCurrent;constructor(e,t){this.getMax=e,this.getCurrent=t}handleInput(e){}invalidate(){}render(e){let t=Math.max(0,this.getMax(e)-this.getCurrent(e));return new Array(t).fill("")}};import{Container as hn,Spacer as b,Text as v}from"@earendil-works/pi-tui";var dn="User wants to chat about this. Continue the conversation to help them decide.",mn="User wants to chat about this",w="(no input)";function y(n,e){switch(n.kind){case"chat":return e==="envelope"?dn:mn;case"multi":return n.selected&&n.selected.length>0?n.selected.join(", "):w;case"custom":return n.answer&&n.answer.length>0?n.answer:w;case"option":return n.answer??w}}var fn="Notes:",se=class{footerRowCount=4;config;constructor(e){this.config=e}headingRows(e){let t=[],i=this.config.questions[e.currentTab];return!this.config.isMulti&&i?.header&&i.header.length>0&&(t.push(new v(this.config.theme.bg("selectedBg",` ${i.header} `),1,0)),t.push(new b(1))),i&&(t.push(new v(this.config.theme.bold(i.question),1,0)),t.push(new b(1))),t}bodyComponent(e){let t=this.config.questions[e.currentTab],i=this.config.tabsByIndex[e.currentTab]?.multiSelect;return t?.multiSelect===!0&&i?i:this.config.getPreviewPane()}bodyHeight(e,t){return this.config.getCurrentBodyHeight(e)}midRows(e){return e.notesVisible?[new v(this.config.theme.fg("muted",fn),1,0),this.config.notesInput,new b(1)]:[]}footerRows(e){let t=this.config.questions[e.currentTab];return[new b(1),this.config.chatRow,new b(1),new v(this.config.theme.fg("dim",bn(t,this.config.isMulti,e)),1,0)]}},ae=class{footerRowCount=5;config;constructor(e){this.config=e}headingRows(e){return[new v(this.config.theme.bold(this.config.theme.fg("accent",rt)),1,0),new b(1)]}bodyComponent(e){let t=new hn;for(let[i,o]of this.config.questions.entries()){let r=e.answers.get(i);if(!r)continue;let s=o.header&&o.header.length>0?o.header:`Q${i+1}`,a=y(r,"summary");t.addChild(new v(this.config.theme.fg("muted",` \u25CF ${s}`),1,0)),t.addChild(new v(` ${this.config.theme.fg("muted","\u2192")} ${this.config.theme.fg("text",a)}`,1,0)),r.notes&&r.notes.length>0&&t.addChild(new v(this.config.theme.fg("dim",` notes: ${r.notes}`),1,0))}return t}bodyHeight(e,t){return this.bodyComponent(t).render(e).length}midRows(e){return[]}footerRows(e){let t=[];for(let[r,s]of this.config.questions.entries())e.answers.has(r)||t.push(s.header&&s.header.length>0?s.header:`Q${r+1}`);let i=t.length===0?this.config.theme.fg("muted",st):this.config.theme.fg("warning",`${at} ${t.join(", ")}`),o=[new b(1),new v(i,1,0),new b(1)];return this.config.submitPicker?o.push(this.config.submitPicker):(o.push(new b(1)),o.push(new b(1))),o}};function bn(n,e,t){let i=[ue,le];return n?.multiSelect===!0&&i.push(Me),n&&n.multiSelect!==!0&&t.focusedOptionHasPreview&&!t.notesVisible&&i.push(Ne),e&&i.push(Oe),i.push(pe),i.join(" \xB7 ")}var ue="Enter to select",le="\u2191/\u2193 to navigate",Me="Space to toggle",Ne="n to add notes",Oe="Tab to switch questions",pe="Esc to cancel",go=[ue,le,pe].join(" \xB7 "),wo=[ue,le,Oe,pe].join(" \xB7 "),yo=` \xB7 ${Me}`,vo=` \xB7 ${Ne}`,rt="Review your answers",st="Ready to submit your answers?",at="\u26A0 Answer remaining questions before submitting:",ce=class{liveProps;config;questionStrategy;submitStrategy;maxFooterRowCount;constructor(e,t){this.config=e,this.liveProps=t,this.questionStrategy=new se({theme:e.theme,questions:e.questions,getPreviewPane:()=>this.liveProps.activePreviewPane,tabsByIndex:e.tabsByIndex,notesInput:e.notesInput,chatRow:e.chatRow,isMulti:e.isMulti,getCurrentBodyHeight:e.getCurrentBodyHeight}),this.submitStrategy=e.isMulti?new ae({theme:e.theme,questions:e.questions,submitPicker:e.submitPicker}):void 0,this.maxFooterRowCount=Math.max(this.questionStrategy.footerRowCount,this.submitStrategy?.footerRowCount??0)}setProps(e){this.liveProps=e}handleInput(e){}invalidate(){}render(e){let i=this.config.isMulti&&this.liveProps.state.currentTab===this.config.questions.length&&this.submitStrategy?this.submitStrategy:this.questionStrategy;return this.buildContainerFromStrategy(i).render(e)}buildContainerFromStrategy(e){let{theme:t,isMulti:i,tabBar:o}=this.config,r=this.liveProps.state,s=new wn,a=()=>new gn(u=>t.fg("accent",u));s.addChild(a()),i&&o&&s.addChild(o),s.addChild(new ut(1));for(let u of e.headingRows(r))s.addChild(u);s.addChild(e.bodyComponent(r)),s.addChild(new ut(1));for(let u of e.midRows(r))s.addChild(u);s.addChild(a());for(let u of e.footerRows(r))s.addChild(u);return s.addChild(new re(u=>this.config.getBodyHeight(u)+this.maxFooterRowCount,u=>e.bodyHeight(u,r)+e.footerRowCount)),s}};function de(n,e,t){let i=n[e];if(!i)return!1;let o=i.options[t];return!!o&&typeof o.preview=="string"&&o.preview.length>0}function lt(n){let e=n.filter(t=>c[t.kind].numbered).length;return{offset:e,total:e+1}}function pt(n,e,t,i){let o=n[e];if(!o||o.multiSelect===!0)return;let r=t.get(e);if(!r||r.kind==="chat")return;if(r.kind==="custom"){let a=i.findIndex(u=>u.kind==="other");return a<0?void 0:{index:a,labelOverride:r.answer??""}}if(r.kind!=="option"||typeof r.answer!="string")return;let s=i.findIndex(a=>a.kind==="option"&&a.label===r.answer);if(!(s<0))return{index:s}}function C(n,e){return e<=0?0:Math.min(n,e-1)}function ct(n,e,t){let i=C(e,t);return n[i]??[]}function dt(n,e){return n.notesVisible?"notes":n.currentTab===e?"submit":n.chatFocused?"chat":"options"}var me=class{tui;questions;itemsByTab;tabsByIndex;inlineInput;globalBindings;perTabBindings;extraInvalidatables;constructor(e){this.tui=e.tui,this.questions=e.questions,this.itemsByTab=e.itemsByTab,this.tabsByIndex=e.tabsByIndex,this.inlineInput=e.inlineInput,this.globalBindings=e.globalBindings,this.perTabBindings=e.perTabBindings,this.extraInvalidatables=e.extraInvalidatables??[]}apply(e){let t=this.questions.length,i=dt(e,t),o=C(e.currentTab,t),r=this.tabsByIndex[o]?.preview??this.tabsByIndex[0]?.preview;if(!r)throw new Error("apply: tabsByIndex is empty \u2014 QuestionnairePropsAdapter requires at least one tab");let s={questions:this.questions,itemsByTab:this.itemsByTab,totalQuestions:t,activeView:i,inputBuffer:this.inlineInput.getValue(),inputCursor:this.inlineInput.getCursor(),activePreviewPane:r};for(let a of this.globalBindings)a.apply(e,s);for(let[a,u]of this.tabsByIndex.entries()){let l={...s,tab:u,i:a};for(let p of this.perTabBindings)p.apply(e,l)}this.tui.requestRender()}invalidate(){for(let e of this.globalBindings)e.invalidate();for(let e of this.tabsByIndex)e.optionList.invalidate(),e.preview.invalidate(),e.multiSelect?.invalidate();for(let e of this.extraInvalidatables)e.invalidate()}};var mt=(n,e)=>{let t=e.questions[e.i];if(!t)return{rows:[],nextActive:!1,nextLabel:c.next.label};let i=e.activeView==="options",o=[];for(let u=0;u<t.options.length;u++)o.push({checked:n.multiSelectChecked.has(u),active:i&&u===n.optionIndex});let r=i&&n.optionIndex===t.options.length,a=e.i===e.questions.length-1?Ze:c.next.label;return{rows:o,nextActive:r,nextLabel:a}},ht=(n,e)=>{let t=e.itemsByTab[e.i]??[],i=e.activeView==="options",o=pt(e.questions,n.currentTab,n.answers,t);return{selectedIndex:n.optionIndex,focused:i,inputBuffer:e.inputBuffer,inputCursor:e.inputCursor,...o?{confirmed:o}:{}}},ft=(n,e)=>{let t=e.activeView==="submit";return{rows:[{active:t&&n.submitChoiceIndex===0},{active:t&&n.submitChoiceIndex===1}]}},bt=(n,e)=>({notesVisible:n.notesVisible,selectedIndex:n.optionIndex,focused:e.activeView==="options"}),gt=(n,e)=>({tabs:e.questions.map((i,o)=>({label:i.header&&i.header.length>0?i.header:`Q${o+1}`,answered:n.answers.has(o),active:o===n.currentTab})),submit:{active:n.currentTab===e.questions.length,allAnswered:n.answers.size===e.questions.length&&e.questions.length>0}}),wt=(n,e)=>{let t=ct(e.itemsByTab,n.currentTab,e.totalQuestions);return{focused:e.activeView==="chat",numbering:lt(t)}},yt=(n,e)=>({state:n,activePreviewPane:e.activePreviewPane});function vn(n){return e=>({current:n.naturalHeight(e),max:n.maxNaturalHeight(e)})}function Tn(n){return e=>{let t=n.naturalHeight(e);return{current:t,max:t}}}var Tt=(n,e)=>e.i===C(n.currentTab,e.totalQuestions);function xt(n){return new Qe(n).build()}var Qe=class{tui;theme;questions;itemsByTab;isMulti;initialState;getCurrentTab;selectTheme;markdownTheme=yn();chatRow;notesInput=new vt;inlineInput=new vt;getTerminalWidth=()=>this.tui.terminal.columns;constructor(e){this.tui=e.tui,this.theme=e.theme,this.questions=e.questions,this.itemsByTab=e.itemsByTab,this.isMulti=e.isMulti,this.initialState=e.initialState,this.getCurrentTab=e.getCurrentTab,this.selectTheme=this.makeSelectTheme(),this.chatRow=new G({item:{kind:"chat",label:c.chat.label},theme:this.selectTheme})}build(){let e=this.buildTabComponents();this.injectGlobalLeftWidth(e);let t=this.buildSubmitPicker(),i=this.buildTabBar(),o=this.buildHeightComputers(e),r=this.buildDialog(e,t,i,o),s=this.buildGlobalBindings(r,t,i),a=this.buildPerTabBindings(),u=this.buildAdapter(e,s,a);return this.handle(u,r)}makeSelectTheme(){let e=this.theme;return{selectedText:t=>e.fg("accent",e.bold(t)),description:t=>e.fg("muted",t),scrollInfo:t=>e.fg("dim",t)}}buildTabComponents(){return this.questions.map((e,t)=>this.buildTabFor(e,t))}buildTabFor(e,t){let i=new Y({items:this.itemsByTab[t]??[],theme:this.selectTheme}),o=new q({question:e,theme:this.theme,markdownTheme:this.markdownTheme}),r=new ne({question:e,getTerminalWidth:this.getTerminalWidth,optionListView:i,previewBlock:o}),s=e.multiSelect?new X(this.theme,e):void 0,a=this.buildBodyHeights(e,r,s);return{optionList:i,preview:r,multiSelect:s,bodyHeights:a}}buildBodyHeights(e,t,i){return e.multiSelect&&i?Tn(i):vn(t)}injectGlobalLeftWidth(e){let t=this.questions,i=this.itemsByTab,o=t.map(s=>({multiSelect:s.multiSelect})),r=s=>it(o,i,t,s);for(let s of e)s.preview.setGlobalLeftWidth(r)}buildSubmitPicker(){return this.isMulti?new ie(this.theme):void 0}buildTabBar(){return this.isMulti?new oe(this.theme):void 0}buildHeightComputers(e){return{global:o=>{let r=0;for(let s of e){let a=s.bodyHeights(o).max;a>r&&(r=a)}return Math.max(1,r)},current:o=>{let r=Math.min(this.getCurrentTab(),e.length-1);return Math.max(0,e[r]?.bodyHeights(o).current??0)}}}pickInitialActivePreview(e){let t=C(this.initialState.currentTab,this.questions.length),i=e[t]?.preview??e[0]?.preview;if(!i)throw new Error("pickInitialActivePreview: tabs is empty \u2014 buildTabComponents must produce at least one tab");return i}buildDialog(e,t,i,o){return new ce({theme:this.theme,questions:this.questions,tabBar:i,notesInput:this.notesInput,chatRow:this.chatRow,isMulti:this.isMulti,tabsByIndex:e,submitPicker:t,getBodyHeight:o.global,getCurrentBodyHeight:o.current},{state:this.initialState,activePreviewPane:this.pickInitialActivePreview(e)})}buildGlobalBindings(e,t,i){return[O({component:e,select:yt}),O({component:this.chatRow,select:wt}),...t?[O({component:t,select:ft})]:[],...i?[O({component:i,select:gt})]:[]]}buildPerTabBindings(){return[U({resolve:e=>e.optionList,predicate:Tt,select:ht}),U({resolve:e=>e.preview,predicate:Tt,select:bt}),U({resolve:e=>e.multiSelect,select:mt})]}buildAdapter(e,t,i){return new me({tui:this.tui,questions:this.questions,itemsByTab:this.itemsByTab,tabsByIndex:e,inlineInput:this.inlineInput,globalBindings:t,perTabBindings:i,extraInvalidatables:[this.notesInput]})}handle(e,t){return{adapter:e,notesInput:this.notesInput,inlineInput:this.inlineInput,render:i=>t.render(i),invalidate:()=>e.invalidate()}}};import{Key as he,matchesKey as fe}from"@earendil-works/pi-tui";var be="tui.select.up",V="tui.select.down",k="tui.select.confirm",B="tui.select.cancel",xn="n",Sn=" ";function H(n,e){return e<=0?0:(n%e+e)%e}function In(n){return n.isMulti?n.questions.length+1:1}function ge(n,e){if(e.isMulti)return n.currentTab<e.questions.length-1?n.currentTab+1:e.questions.length}function De(n,e){let t=e.questions[n.currentTab];if(!t)return null;let i=e.currentItem;if(i?.kind==="chat")return{questionIndex:n.currentTab,question:t.question,kind:"chat",answer:i.label};if(n.inputMode){let o=e.inputBuffer;return{questionIndex:n.currentTab,question:t.question,kind:"custom",answer:o.length>0?o:null}}return!i||i.kind==="other"||i.kind==="next"?null:{questionIndex:n.currentTab,question:t.question,kind:"option",answer:i.label}}function An(n,e){let t=e.questions[n.currentTab];if(!t)return[];let i=[];for(let o=0;o<t.options.length;o++)if(n.multiSelectChecked.has(o)){let r=t.options[o]?.label;typeof r=="string"&&i.push(r)}return i}function Le(n,e,t){if(!t.isMulti)return null;let i=In(t);return fe(n,he.tab)||fe(n,he.right)?{kind:"tab_switch",nextTab:H(e.currentTab+1,i)}:fe(n,he.shift("tab"))||fe(n,he.left)?{kind:"tab_switch",nextTab:H(e.currentTab-1,i)}:null}function St(n,e){return e.items.length>0&&n.optionIndex===e.items.length-1?{kind:"focus_chat"}:{kind:"nav",nextIndex:H(n.optionIndex+1,Math.max(1,e.items.length))}}function It(n,e){return e.items.length>0&&n.optionIndex===0?{kind:"focus_chat"}:{kind:"nav",nextIndex:H(n.optionIndex-1,Math.max(1,e.items.length))}}function At(n,e,t){let i=t.keybindings;if(e.notesVisible)return i.matches(n,B)?{kind:"notes_exit"}:i.matches(n,k)?{kind:"notes_exit"}:{kind:"notes_forward",data:n};if(e.chatFocused){if(i.matches(n,B))return{kind:"cancel"};if(i.matches(n,k)){let a=De(e,t);return a?{kind:"confirm",answer:a,autoAdvanceTab:ge(e,t)}:{kind:"ignore"}}if(i.matches(n,be))return{kind:"focus_options",optionIndex:Math.max(0,t.items.length-1)};if(i.matches(n,V))return{kind:"focus_options",optionIndex:0};let s=Le(n,e,t);return s||{kind:"ignore"}}if(e.inputMode){if(i.matches(n,k)){let s=De(e,t);return s?{kind:"confirm",answer:s,autoAdvanceTab:ge(e,t)}:{kind:"ignore"}}return i.matches(n,B)?{kind:"cancel"}:i.matches(n,be)?It(e,t):i.matches(n,V)?St(e,t):{kind:"ignore"}}if(t.isMulti&&e.currentTab===t.questions.length){if(i.matches(n,B))return{kind:"cancel"};let s=Le(n,e,t);if(s)return s;if(i.matches(n,be)||i.matches(n,V)){let a=i.matches(n,V)?1:-1;return{kind:"submit_nav",nextIndex:H(e.submitChoiceIndex+a,2)===1?1:0}}return i.matches(n,k)?e.submitChoiceIndex===1?{kind:"cancel"}:{kind:"submit"}:{kind:"ignore"}}let o=Le(n,e,t);if(o)return o;let r=t.questions[e.currentTab];if(!r)return{kind:"ignore"};if(n===xn&&!r.multiSelect&&e.focusedOptionHasPreview)return{kind:"notes_enter"};if(i.matches(n,be))return It(e,t);if(i.matches(n,V))return St(e,t);if(r.multiSelect){let s=t.currentItem?.kind,a=s?c[s]:void 0;return n===Sn?a?.blocksMultiToggle?{kind:"ignore"}:{kind:"toggle",index:e.optionIndex}:i.matches(n,k)?a?.autoSubmitsInMulti?{kind:"multi_confirm",selected:An(e,t),autoAdvanceTab:ge(e,t)}:{kind:"toggle",index:e.optionIndex}:i.matches(n,B)?{kind:"cancel"}:{kind:"ignore"}}if(i.matches(n,k)){let s=De(e,t);return s?{kind:"confirm",answer:s,autoAdvanceTab:ge(e,t)}:{kind:"ignore"}}return i.matches(n,B)?{kind:"cancel"}:{kind:"ignore"}}function _n(n,e){let t=[];for(let i=0;i<e.length;i++){let o=n.answers.get(i);o&&t.push(o)}return t}function qe(n,e){let t=de(e,n.currentTab,n.optionIndex);return n.focusedOptionHasPreview===t?n:{...n,focusedOptionHasPreview:t}}function _t(n,e,t){let i=e[t];if(!i?.multiSelect)return new Set;let r=n.get(t)?.selected??[],s=new Set;for(let[a,u]of i.options.entries())r.includes(u.label)&&s.add(a);return s}function En(n,e){let t=e.questions[n.currentTab];if(!t?.multiSelect)return n.answers;let i=[];for(let[s,a]of t.options.entries())n.multiSelectChecked.has(s)&&i.push(a.label);let o=new Map(n.answers);if(i.length===0)return o.delete(n.currentTab),o;let r=n.notesByTab.get(n.currentTab);return o.set(n.currentTab,{questionIndex:n.currentTab,question:t.question,kind:"multi",answer:null,selected:i,...r&&r.length>0?{notes:r}:{}}),o}function We(n,e,t){let i=n.notesByTab.get(e)??n.answers.get(e)?.notes??"",o={...n,currentTab:e,optionIndex:0,inputMode:!1,notesVisible:!1,chatFocused:!1,submitChoiceIndex:0,multiSelectChecked:_t(n.answers,t.questions,e),notesDraft:i};return{state:qe(o,t.questions),effects:[{kind:"set_notes_focused",focused:!1},{kind:"set_notes_value",value:i}]}}function $(n,e,t){let i={answers:_n(n,e.questions),cancelled:t};return{state:n,effects:[{kind:"done",result:i}]}}var Pn=(n,e,t)=>{let o=(t.itemsByTab[n.currentTab]??[])[e.nextIndex],r=o?c[o.kind].activatesInputMode:!1,s=qe({...n,optionIndex:e.nextIndex,inputMode:r},t.questions);if(!r)return{state:s,effects:[{kind:"clear_input_buffer"}]};let a=n.answers.get(n.currentTab);return a?.kind==="custom"&&typeof a.answer=="string"?{state:s,effects:[{kind:"set_input_buffer",value:a.answer}]}:{state:s,effects:[]}},Rn=(n,e,t)=>We(n,e.nextTab,t),Cn=(n,e,t)=>{let i=e.answer;if(i.kind==="option"&&i.answer){let u=t.questions[i.questionIndex]?.options.find(l=>l.label===i.answer);u?.preview&&u.preview.length>0&&(i={...i,preview:u.preview})}let o=n.notesByTab.get(i.questionIndex);o&&o.length>0&&(i={...i,notes:o});let r=new Map(n.answers);r.set(i.questionIndex,i);let s={...n,answers:r};return i.kind==="chat"?$(s,t,!1):e.autoAdvanceTab!==void 0?We(s,e.autoAdvanceTab,t):$(s,t,!1)},kn=(n,e,t)=>{let i=new Set(n.multiSelectChecked);i.has(e.index)?i.delete(e.index):i.add(e.index);let o={...n,multiSelectChecked:i},r=En(o,t);return{state:{...o,answers:r},effects:[]}},Bn=(n,e,t)=>{let i=t.questions[n.currentTab];if(!i)return{state:n,effects:[]};let o=n.notesByTab.get(n.currentTab),r=new Map(n.answers);r.set(n.currentTab,{questionIndex:n.currentTab,question:i.question,kind:"multi",answer:null,selected:e.selected,...o&&o.length>0?{notes:o}:{}});let s={...n,answers:r,multiSelectChecked:_t(r,t.questions,n.currentTab)};return e.autoAdvanceTab!==void 0?We(s,e.autoAdvanceTab,t):$(s,t,!1)},Mn=(n,e,t)=>{let i=n.notesByTab.get(n.currentTab)??n.answers.get(n.currentTab)?.notes??"";return{state:{...n,notesVisible:!0,notesDraft:i},effects:[{kind:"set_notes_value",value:i},{kind:"set_notes_focused",focused:!0}]}},Nn=(n,e,t)=>{let i=n.notesDraft.trim(),o=new Map(n.notesByTab),r=new Map(n.answers);if(i.length===0){o.delete(n.currentTab);let s=r.get(n.currentTab);if(s?.notes){let a={...s};a.notes=void 0,r.set(n.currentTab,a)}}else{o.set(n.currentTab,i);let s=r.get(n.currentTab);s&&r.set(n.currentTab,{...s,notes:i})}return{state:{...n,notesByTab:o,answers:r,notesVisible:!1},effects:[{kind:"set_notes_focused",focused:!1}]}},On=(n,e,t)=>{let o=(t.itemsByTab[n.currentTab]??[])[e.optionIndex],r=o?c[o.kind].activatesInputMode:!1;return{state:qe({...n,chatFocused:!1,optionIndex:e.optionIndex,inputMode:r},t.questions),effects:r?[]:[{kind:"clear_input_buffer"}]}},Qn=(n,e,t)=>$(n,t,!0),Dn=(n,e,t)=>$(n,t,!1),Ln=(n,e,t)=>({state:{...n,submitChoiceIndex:e.nextIndex},effects:[]}),qn=(n,e,t)=>({state:{...n,chatFocused:!0},effects:[]}),Wn=(n,e,t)=>({state:n,effects:[{kind:"forward_notes_keystroke",data:e.data}]}),Vn=(n,e,t)=>({state:n,effects:[]}),Hn={nav:Pn,tab_switch:Rn,confirm:Cn,toggle:kn,multi_confirm:Bn,cancel:Qn,notes_enter:Mn,notes_exit:Nn,notes_forward:Wn,submit:Dn,submit_nav:Ln,focus_chat:qn,focus_options:On,ignore:Vn};function Et(n,e,t){let i=Hn[e.kind];return i(n,e,t)}var jn="";function Fn(){return{currentTab:0,optionIndex:0,inputMode:!1,notesVisible:!1,chatFocused:!1,answers:new Map,multiSelectChecked:new Set,notesByTab:new Map,focusedOptionHasPreview:!1,submitChoiceIndex:0,notesDraft:""}}var we=class{state=Fn();questions;isMulti;itemsByTab;notesInput;inlineInput;viewAdapter;tui;done;component;constructor(e){this.tui=e.tui,this.done=e.done,this.questions=e.params.questions,this.isMulti=this.questions.length>1,this.itemsByTab=e.itemsByTab,this.state={...this.state,focusedOptionHasPreview:de(this.questions,0,0)};let t=xt({tui:this.tui,theme:e.theme,questions:this.questions,itemsByTab:this.itemsByTab,isMulti:this.isMulti,initialState:this.state,getCurrentTab:()=>this.state.currentTab});this.notesInput=t.notesInput,this.inlineInput=t.inlineInput,this.viewAdapter=t.adapter,this.component={render:t.render,invalidate:t.invalidate,handleInput:i=>this.dispatch(i)},this.viewAdapter.apply(this.state)}dispatch(e){let t=At(e,this.state,this.runtime());if(t.kind==="ignore"){this.handleIgnoreInline(e);return}this.commit(t)}commit(e){let t=Et(this.state,e,this.applyContext());this.state=t.state;for(let i of t.effects)this.runEffect(i);this.state=this.mirrorNotesDraft(this.state),this.viewAdapter.apply(this.state)}mirrorNotesDraft(e){let t=this.notesInput.getValue();return e.notesDraft===t?e:{...e,notesDraft:t}}runEffect(e){switch(e.kind){case"set_input_buffer":this.inlineInput.setValue(e.value),this.inlineInput.handleInput(jn);return;case"clear_input_buffer":this.inlineInput.setValue("");return;case"set_notes_value":this.notesInput.setValue(e.value);return;case"set_notes_focused":this.notesInput.focused=e.focused;return;case"forward_notes_keystroke":this.notesInput.handleInput(e.data);return;case"done":this.done(e.result);return}}handleIgnoreInline(e){this.state.inputMode&&(this.inlineInput.handleInput(e),this.viewAdapter.apply(this.state))}runtime(){return{keybindings:$n(),inputBuffer:this.inlineInput.getValue(),questions:this.questions,isMulti:this.isMulti,currentItem:this.currentItem(),items:this.itemsByTab[this.state.currentTab]??[]}}applyContext(){return{questions:this.questions,itemsByTab:this.itemsByTab}}currentItem(){if(this.state.chatFocused)return{kind:"chat",label:c.chat.label};let e=this.itemsByTab[this.state.currentTab]??[];return this.state.optionIndex<e.length?e[this.state.optionIndex]:{kind:"chat",label:c.chat.label}}};var Un="ask-user",ye=" - ";function Ve(n,e){let t=e.fg("toolTitle",e.bold(Un));switch(n.kind){case"preparing":return`${t}${ye}${e.fg("dim","preparing...")}`;case"waiting":case"answered":{let i=e.fg("accent",Gn(n.questionCount));return`${t}${ye}${i}`}case"declined":return`${t}${ye}${e.fg("warning","declined")}`;case"error":{let i=n.code!==void 0&&n.code.length>0?`error: ${n.code}`:"error";return`${t}${ye}${e.fg("error",i)}`}default:return Ct(n)}}function Gn(n){return n===1?"1 question":`${n} questions`}var Pt=60,Kn="*",Xn="->",Yn="chat about this";function Rt(n,e,t){if(n.length===0)return[];let i=Zn(n),o=[];for(let r=0;r<n.length;r++){let s=n[r],a=e.find(u=>u.questionIndex===r);o.push(ei(s,a,i,t))}return o}function Zn(n){let e=0;for(let t of n)t.header.length>e&&(e=t.header.length);return e}function zn(n,e){return n.length>=e?n:n+" ".repeat(e-n.length)}function Jn(n){let e=n.length;return e<=Pt?{display:n,truncated:!1,length:e}:{display:`${n.slice(0,Pt-3)}...`,truncated:!0,length:e}}function ei(n,e,t,i){let o=i.fg("muted",Kn),r=i.fg("dim",zn(n.header,t)),s=i.fg("muted",Xn),a=ti(e,i),u=ni(e,i);return` ${o} ${r} ${s} ${a}${u}`}function ti(n,e){if(!n)return e.fg("dim",w);switch(n.kind){case"chat":return e.fg("dim",`(${Yn})`);case"custom":{let t=y(n,"summary");if(t===w)return e.fg("dim",t);let{display:i,truncated:o,length:r}=Jn(t),s=e.fg("accent",`"${i}"`);return o?s+e.fg("muted",` - ${r} chars`):s}case"option":case"multi":{let t=y(n,"summary");return t===w?e.fg("dim",t):e.fg("accent",t)}default:return Ct(n.kind)}}function ni(n,e){if(!n)return"";let t="";return n.notes&&n.notes.length>0&&(t+=e.fg("muted"," - notes")),n.preview&&n.preview.length>0&&(t+=e.fg("muted"," - preview")),t}function Ct(n){throw new Error(`Unhandled discriminant: ${JSON.stringify(n)}`)}var kt="User declined to answer questions",ii="User has answered your questions:",oi="You can now continue with the user's answers in mind.";function Bt(n,e){if(!n||n.cancelled)return M(kt,{answers:n?.answers??[],cancelled:!0});let t=[];for(let i=0;i<e.questions.length;i++){let o=n.answers.find(r=>r.questionIndex===i);o&&t.push(ri(o))}return t.length===0?M(kt,{answers:n.answers,cancelled:!0}):M(`${ii} ${t.join(" ")} ${oi}`,n)}function ri(n){let e=[`"${n.question}"="${y(n,"envelope")}"`];return n.preview&&n.preview.length>0&&e.push(`selected preview: ${n.preview}`),n.notes&&n.notes.length>0&&e.push(`user notes: ${n.notes}`),`${e.join(". ")}.`}function M(n,e){return{content:[{type:"text",text:n}],details:e}}import{Type as h}from"@sinclair/typebox";var I=4,A=2,ve=4,j=16,S=60;var He=["Other",c.other.label,c.chat.label,c.next.label],si=h.Object({label:h.String({maxLength:S,description:`MAX ${S} CHARACTERS \u2014 hard limit, requests over the limit are rejected. The display text for this option that the user will see and select. Should be concise (1-5 words) and clearly describe the choice. Do NOT append "(Recommended)" to the label text \u2014 set the "recommended" flag on the option instead; the renderer adds the marker automatically.`}),description:h.String({description:"Explanation of what this option means or what will happen if chosen. Useful for providing context about trade-offs or implications."}),preview:h.Optional(h.String({description:"Optional preview content rendered when this option is focused. Use for mockups, code snippets, or visual comparisons that help users compare options. See the tool description for the expected content format."})),recommended:h.Optional(h.Boolean({description:`If true, the renderer marks this option as the recommended choice by appending "(Recommended)" after the label at display time. Use this instead of typing "(Recommended)" into the label yourself \u2014 that text counts against the ${S}-character label cap and the schema will reject it.`}))}),ai=h.Object({question:h.String({description:'The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"'}),header:h.String({maxLength:j,description:`MAX ${j} CHARACTERS \u2014 hard limit, requests over the limit are rejected. Very short chip/tag shown next to the question. Examples: "Auth method", "Library", "Approach".`}),options:h.Array(si,{minItems:A,maxItems:ve,description:"The available choices for this question. Must have 2-4 options. Each option should be a distinct, mutually exclusive choice (unless multiSelect is enabled). The 'Type something.' row is appended automatically \u2014 do NOT author it."}),multiSelect:h.Optional(h.Boolean({default:!1,description:"Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive."}))}),ui=h.Array(ai,{minItems:1,maxItems:I,description:"Questions to ask the user (1-4 questions)"}),Mt=h.Object({questions:ui});var li="Error: At least one question is required",pi=`Error: At most ${I} questions are allowed per invocation`,ci="Error: Question text must be unique within an invocation",di=`Error: Each question requires at least ${A} options`,mi=`Error: Option label is reserved (${He.join(", ")})`,hi="Error: Option labels must be unique within a question",fi=new Set(He);function Nt(n){if(n.questions.length===0)return{ok:!1,error:"no_questions",message:li};if(n.questions.length>I)return{ok:!1,error:"too_many_questions",message:pi};let e=new Set;for(let t of n.questions){if(e.has(t.question))return{ok:!1,error:"duplicate_question",message:ci};e.add(t.question)}for(let t of n.questions){if(t.options.length<A)return{ok:!1,error:"empty_options",message:di};let i=new Set;for(let o of t.options){if(fi.has(o.label))return{ok:!1,error:"reserved_label",message:mi};if(i.has(o.label))return{ok:!1,error:"duplicate_option_label",message:hi};i.add(o.label)}}return{ok:!0}}var gi="Error: UI not available (running in non-interactive mode)",Ot=" (Recommended)",wi="\u2026";function Dt(n,e){let t=Array.from(n);return t.length<=e?n:`${t.slice(0,e-1).join("")}${wi}`}function yi(n){if(!n||typeof n!="object")return n;let e=n;if(typeof e.label!="string")return n;let t=e.label,i=!1,o=!1;return t.endsWith(Ot)&&(t=t.slice(0,t.length-Ot.length),e.recommended==null&&(i=!0),o=!0),t.length>S&&(t=Dt(t,S),o=!0),o?i?{...n,label:t,recommended:!0}:{...n,label:t}:n}function vi(n){if(!n||typeof n!="object")return n;let e=n,t=e.header,i=!1;typeof e.header=="string"&&e.header.length>j&&(t=Dt(e.header,j),i=!0);let o=e.options,r=!1;if(Array.isArray(e.options)){let s=e.options,a=s.map(yi);r=a.some((u,l)=>u!==s[l]),r&&(o=a)}return i||r?{...n,header:t,options:o}:n}function Ti(n){if(!n||typeof n!="object")return n;let e=n;if(!Array.isArray(e.questions))return n;let t=e.questions,i=t.map(vi);return i.some((r,s)=>r!==t[s])?{...e,questions:i}:n}function xi(n){let e=n.options.map(i=>({kind:"option",label:i.label,description:i.description,...i.recommended===!0?{recommended:!0}:{}})),t=n.options.some(i=>typeof i.preview=="string"&&i.preview.length>0);for(let i of Fe(n,t))e.push({kind:i,label:c[i].label});return e}function Qt(n){let{args:e,executionStarted:t,argsComplete:i,result:o}=n;if(o){if(o.isError)return{kind:"error",code:o.details?.error};if(o.details?.cancelled)return{kind:"declined"};let r=e?.questions??[],s=o.details?.answers??[];return{kind:"answered",questionCount:r.length,unanswered:Si(r,s)}}return i&&t?{kind:"waiting",questionCount:e?.questions?.length??0}:{kind:"preparing"}}function Si(n,e){let t=0;for(let i=0;i<n.length;i++){let o=e.find(r=>r.questionIndex===i);if(!o){t++;continue}if(o.kind==="chat"){t++;continue}y(o,"summary")===w&&t++}return t}function Lt(n){n.registerTool({name:"ask-user",label:"Ask User Question",description:`Ask the user one or more structured questions during execution. Use when you need to:
3
+ 1. Gather user preferences or requirements
4
+ 2. Clarify ambiguous instructions
5
+ 3. Get decisions on implementation choices as you work
6
+ 4. Offer choices to the user about what direction to take
7
+
8
+ Usage notes:
9
+ - Users will always be able to type a custom answer ("Type something." row is appended automatically to every single-select question) or pick "Chat about this" to abandon the questionnaire and continue in free-form conversation. Do NOT author "Other" / "Type something." / "Chat about this" labels yourself \u2014 duplicates are rejected at runtime.
10
+ - Use multiSelect: true to allow multiple answers to be selected for a question. The "Type something." row is suppressed on multi-select questions, and is ALSO suppressed on single-select questions where any option carries a \`preview\` (the side-by-side layout has no room for inline custom text \u2014 "Chat about this" remains as the free-form escape hatch).
11
+ - Every option's \`label\` is capped at 60 characters and every question's \`header\` at 16 characters \u2014 over-limit values are rejected by the tool schema.
12
+ - If one option is your recommendation, make it the first option in the list AND set \`recommended: true\` on it. Do NOT append "(Recommended)" to the label text \u2014 that suffix counts against the 60-character label budget; the renderer adds the marker automatically when \`recommended\` is set.
13
+
14
+ Preview feature:
15
+ Use the optional \`preview\` field on options when presenting concrete artifacts that users need to visually compare:
16
+ - ASCII mockups of UI layouts or components
17
+ - Code snippets showing different implementations
18
+ - Diagram variations
19
+ - Configuration examples
20
+
21
+ Preview content is rendered as markdown in a monospace box. Multi-line text with newlines is supported. When any option has a preview, the UI switches to a side-by-side layout with a vertical option list on the left and preview on the right. Do not use previews for simple preference questions where labels and descriptions suffice. Note: previews are only supported for single-select questions (not multiSelect).`,promptSnippet:`Ask the user up to ${I} structured questions (${A}-${ve} options each) when requirements are ambiguous`,promptGuidelines:[`Use ask-user whenever the user's request is underspecified and you cannot proceed without concrete decisions \u2014 you can ask up to ${I} questions per invocation.`,`Each question MUST have ${A}-${ve} options. Every option requires a concise label (1-5 words) and a description explaining what the choice means or its trade-offs. The user can additionally type a custom answer ("Type something." row is appended automatically to single-select questions) or pick "Chat about this" to abandon the questionnaire.`,`Set multiSelect: true when multiple answers are valid; this suppresses the "Type something." row. Provide an options[].preview markdown string when an option benefits from richer side-by-side context (mockups, code snippets, diagrams, configs) \u2014 single-select only. NOTE: any non-empty preview on a single-select question ALSO suppresses the "Type something." row (no room in the side-by-side layout); "Chat about this" remains the escape hatch. If you recommend a specific option, make it the first option and set recommended: true on it (do NOT type "(Recommended)" into the label \u2014 the renderer adds the marker, and the suffix would count against the ${S}-character label cap). The recommended flag is only meaningful on single-select questions \u2014 do not set it on multi-select options, where "choose any that apply" makes a single-row recommendation semantically odd.`,"Do not stack multiple ask-user calls back-to-back \u2014 group all clarifying questions into one invocation."],parameters:Mt,prepareArguments:Ti,defaultExpanded:!0,renderCall(e,t,i){let o=i.lastComponent??new Te("",0,0);if(i.argsComplete&&i.executionStarted&&!i.isPartial)return o.setText(""),o;let r=Qt({args:e,executionStarted:i.executionStarted,argsComplete:i.argsComplete,isPartial:i.isPartial,result:void 0});return o.setText(Ve(r,t)),o},renderResult(e,t,i,o){let r=o.lastComponent??new bi;r.clear();let s=Qt({args:o.args,executionStarted:o.executionStarted,argsComplete:o.argsComplete,isPartial:o.isPartial,result:{isError:o.isError,details:e.details}});if(r.addChild(new Te(Ve(s,i),0,0)),s.kind==="error"){let a=e.content[0];return a?.type==="text"&&a.text.length>0&&r.addChild(new Te(` ${i.fg("toolOutput",a.text)}`,0,0)),r}if(s.kind==="answered"||s.kind==="declined"){let u=o.args?.questions??[],l=e.details?.answers??[];if(s.kind==="declined"&&l.length===0)return r;for(let p of Rt(u,l,i))r.addChild(new Te(p,0,0))}return r},async execute(e,t,i,o,r){let s=t;if(!r.hasUI)return M(gi,{answers:[],cancelled:!0,error:"no_ui"});let a=Nt(s);if(!a.ok)return M(a.message,{answers:[],cancelled:!0,error:a.error});let u=s.questions.map(p=>xi(p)),l=await r.ui.custom((p,d,m,f)=>new we({tui:p,theme:d,params:s,itemsByTab:u,done:f}).component);return Bt(l,s)}})}var qt="ask-user";function Er(n){Lt(n),n.on("session_start",(e,t)=>{if(t.mode==="interactive")return;let i=n.getActiveTools();i.includes(qt)&&n.setActiveTools(i.filter(o=>o!==qt))})}export{Er as default};
@@ -0,0 +1,20 @@
1
+ {
2
+ "extensions": [
3
+ {
4
+ "name": "ask-user",
5
+ "entry": "ask-user/index.js"
6
+ },
7
+ {
8
+ "name": "mcp",
9
+ "entry": "mcp/index.js"
10
+ },
11
+ {
12
+ "name": "otel",
13
+ "entry": "otel/index.js"
14
+ },
15
+ {
16
+ "name": "migration",
17
+ "entry": "migration/index.js"
18
+ }
19
+ ]
20
+ }