herm-tui 1.11.0-dev.7 → 1.11.0-dev.8
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/index.js +6 -6
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -3642,7 +3642,7 @@ Please report this to https://github.com/markedjs/marked.`,e){let r="<p>An error
|
|
|
3642
3642
|
`)}onResize(width,height){this.invalidateLayoutAndRaster(!1),super.onResize(width,height)}renderSelf(buffer){if(!this.visible||this.isDestroyed)return;if(this._layoutDirty)this.rebuildLayoutForCurrentWidth();if(!this._rasterDirty)return;if(buffer.clear(this._backgroundColor),this._rowCount===0||this._columnCount===0){this._rasterDirty=!1;return}this.drawBorders(buffer),this.drawCells(buffer),this._rasterDirty=!1}destroySelf(){this.destroyCells(),super.destroySelf()}setupMeasureFunc(){let measureFunc=(width,widthMode,_height,_heightMode)=>{let rawWidthConstraint=widthMode!==0&&Number.isFinite(width)?Math.max(1,Math.floor(width)):void 0,widthConstraint=this.resolveLayoutWidthConstraint(rawWidthConstraint),measuredLayout=this.computeLayout(widthConstraint);this._cachedMeasureLayout=measuredLayout,this._cachedMeasureWidth=widthConstraint;let measuredWidth=measuredLayout.tableWidth>0?measuredLayout.tableWidth:1,measuredHeight=measuredLayout.tableHeight>0?measuredLayout.tableHeight:1;if(widthMode===2&&rawWidthConstraint!==void 0&&this._positionType!=="absolute")measuredWidth=Math.min(rawWidthConstraint,measuredWidth);return{width:measuredWidth,height:measuredHeight}};this.yogaNode.setMeasureFunc(measureFunc)}rebuildCells(){let newRowCount=this._content.length,newColumnCount=this._content.reduce((max,row)=>Math.max(max,row.length),0);if(this._cells.length===0){this._rowCount=newRowCount,this._columnCount=newColumnCount,this._cells=[],this._prevCellContent=[];for(let rowIdx=0;rowIdx<newRowCount;rowIdx++){let row=this._content[rowIdx]??[],rowCells=[],rowRefs=[];for(let colIdx=0;colIdx<newColumnCount;colIdx++){let cellContent=row[colIdx];rowCells.push(this.createCell(cellContent)),rowRefs.push(cellContent)}this._cells.push(rowCells),this._prevCellContent.push(rowRefs)}this.invalidateLayoutAndRaster();return}this.updateCellsDiff(newRowCount,newColumnCount),this.invalidateLayoutAndRaster()}updateCellsDiff(newRowCount,newColumnCount){let oldRowCount=this._rowCount,oldColumnCount=this._columnCount,keepRows=Math.min(oldRowCount,newRowCount),keepCols=Math.min(oldColumnCount,newColumnCount);for(let rowIdx=0;rowIdx<keepRows;rowIdx++){let newRow=this._content[rowIdx]??[],cellRow=this._cells[rowIdx],refRow=this._prevCellContent[rowIdx];for(let colIdx=0;colIdx<keepCols;colIdx++){let cellContent=newRow[colIdx];if(cellContent===refRow[colIdx])continue;let oldCell=cellRow[colIdx];oldCell.textBufferView.destroy(),oldCell.textBuffer.destroy(),oldCell.syntaxStyle.destroy(),cellRow[colIdx]=this.createCell(cellContent),refRow[colIdx]=cellContent}if(newColumnCount>oldColumnCount)for(let colIdx=oldColumnCount;colIdx<newColumnCount;colIdx++){let cellContent=newRow[colIdx];cellRow.push(this.createCell(cellContent)),refRow.push(cellContent)}else if(newColumnCount<oldColumnCount){for(let colIdx=newColumnCount;colIdx<oldColumnCount;colIdx++){let cell=cellRow[colIdx];cell.textBufferView.destroy(),cell.textBuffer.destroy(),cell.syntaxStyle.destroy()}cellRow.length=newColumnCount,refRow.length=newColumnCount}}if(newRowCount>oldRowCount)for(let rowIdx=oldRowCount;rowIdx<newRowCount;rowIdx++){let newRow=this._content[rowIdx]??[],rowCells=[],rowRefs=[];for(let colIdx=0;colIdx<newColumnCount;colIdx++){let cellContent=newRow[colIdx];rowCells.push(this.createCell(cellContent)),rowRefs.push(cellContent)}this._cells.push(rowCells),this._prevCellContent.push(rowRefs)}else if(newRowCount<oldRowCount){for(let rowIdx=newRowCount;rowIdx<oldRowCount;rowIdx++){let row=this._cells[rowIdx];for(let cell of row)cell.textBufferView.destroy(),cell.textBuffer.destroy(),cell.syntaxStyle.destroy()}this._cells.length=newRowCount,this._prevCellContent.length=newRowCount}this._rowCount=newRowCount,this._columnCount=newColumnCount}createCell(content){let styledText=this.toStyledText(content),textBuffer=TextBuffer.create(this._ctx.widthMethod),syntaxStyle=SyntaxStyle.create();textBuffer.setDefaultFg(this._defaultFg),textBuffer.setDefaultBg(this._defaultBg),textBuffer.setDefaultAttributes(this._defaultAttributes),textBuffer.setSyntaxStyle(syntaxStyle),textBuffer.setStyledText(styledText);let textBufferView=TextBufferView.create(textBuffer);return textBufferView.setWrapMode(this._wrapMode),{textBuffer,textBufferView,syntaxStyle}}toStyledText(content){if(Array.isArray(content))return new StyledText(content);if(content===null||content===void 0)return stringToStyledText("");return stringToStyledText(String(content))}destroyCells(){for(let row of this._cells)for(let cell of row)cell.textBufferView.destroy(),cell.textBuffer.destroy(),cell.syntaxStyle.destroy();this._cells=[],this._prevCellContent=[],this._rowCount=0,this._columnCount=0,this._layout=this.createEmptyLayout()}rebuildLayoutForCurrentWidth(){let maxTableWidth=this.resolveLayoutWidthConstraint(this.width),layout;if(this._cachedMeasureLayout!==null&&this._cachedMeasureWidth===maxTableWidth)layout=this._cachedMeasureLayout;else layout=this.computeLayout(maxTableWidth);if(this._cachedMeasureLayout=null,this._cachedMeasureWidth=void 0,this._layout=layout,this.applyLayoutToViews(layout),this._layoutDirty=!1,this._lastLocalSelection?.isActive)this.applySelectionToCells(this._lastLocalSelection,!0)}computeLayout(maxTableWidth){if(this._rowCount===0||this._columnCount===0)return this.createEmptyLayout();let borderLayout=this.resolveBorderLayout(),columnWidths=this.computeColumnWidths(maxTableWidth,borderLayout),rowHeights=this.computeRowHeights(columnWidths),columnOffsets=this.computeOffsets(columnWidths,borderLayout.left,borderLayout.right,borderLayout.innerVertical,this.getInterColumnGap(borderLayout)),rowOffsets=this.computeOffsets(rowHeights,borderLayout.top,borderLayout.bottom,borderLayout.innerHorizontal);return{columnWidths,rowHeights,columnOffsets,rowOffsets,columnOffsetsI32:new Int32Array(columnOffsets),rowOffsetsI32:new Int32Array(rowOffsets),tableWidth:(columnOffsets[columnOffsets.length-1]??0)+1,tableHeight:(rowOffsets[rowOffsets.length-1]??0)+1}}isFullWidthMode(){return this._columnWidthMode==="full"}computeColumnWidths(maxTableWidth,borderLayout){let horizontalPadding=this.getHorizontalCellPadding(),intrinsicWidths=Array(this._columnCount).fill(1+horizontalPadding);for(let rowIdx=0;rowIdx<this._rowCount;rowIdx++)for(let colIdx=0;colIdx<this._columnCount;colIdx++){let cell=this._cells[rowIdx]?.[colIdx];if(!cell)continue;let measure=cell.textBufferView.measureForDimensions(0,MEASURE_HEIGHT),measuredWidth=Math.max(1,measure?.widthColsMax??0)+horizontalPadding;intrinsicWidths[colIdx]=Math.max(intrinsicWidths[colIdx],measuredWidth)}if(maxTableWidth===void 0||!Number.isFinite(maxTableWidth)||maxTableWidth<=0)return intrinsicWidths;let maxContentWidth=Math.max(1,Math.floor(maxTableWidth)-this.getVerticalBorderCount(borderLayout)-this.getTotalInterColumnGap(borderLayout)),currentWidth=intrinsicWidths.reduce((sum,width)=>sum+width,0);if(currentWidth===maxContentWidth)return intrinsicWidths;if(currentWidth<maxContentWidth){if(this.isFullWidthMode())return this.expandColumnWidths(intrinsicWidths,maxContentWidth);return intrinsicWidths}if(this._wrapMode==="none")return intrinsicWidths;return this.fitColumnWidths(intrinsicWidths,maxContentWidth)}expandColumnWidths(widths,targetContentWidth){let baseWidths=widths.map((width)=>Math.max(1,Math.floor(width))),totalBaseWidth=baseWidths.reduce((sum,width)=>sum+width,0);if(totalBaseWidth>=targetContentWidth)return baseWidths;let expanded=[...baseWidths],columns=expanded.length,extraWidth=targetContentWidth-totalBaseWidth,sharedWidth=Math.floor(extraWidth/columns),remainder=extraWidth%columns;for(let idx=0;idx<columns;idx++)if(expanded[idx]+=sharedWidth,idx<remainder)expanded[idx]+=1;return expanded}fitColumnWidths(widths,targetContentWidth){if(this._columnFitter==="balanced")return this.fitColumnWidthsBalanced(widths,targetContentWidth);return this.fitColumnWidthsProportional(widths,targetContentWidth)}fitColumnWidthsProportional(widths,targetContentWidth){let minWidth=1+this.getHorizontalCellPadding(),hardMinWidths=Array(widths.length).fill(minWidth),baseWidths=widths.map((width)=>Math.max(1,Math.floor(width))),preferredMinWidths=baseWidths.map((width)=>Math.min(width,minWidth+1)),floorWidths=preferredMinWidths.reduce((sum,width)=>sum+width,0)<=targetContentWidth?preferredMinWidths:hardMinWidths,floorTotal=floorWidths.reduce((sum,width)=>sum+width,0),clampedTarget=Math.max(floorTotal,targetContentWidth),totalBaseWidth=baseWidths.reduce((sum,width)=>sum+width,0);if(totalBaseWidth<=clampedTarget)return baseWidths;let shrinkable=baseWidths.map((width,idx)=>width-floorWidths[idx]),totalShrinkable=shrinkable.reduce((sum,value)=>sum+value,0);if(totalShrinkable<=0)return[...floorWidths];let targetShrink=totalBaseWidth-clampedTarget,integerShrink=Array(baseWidths.length).fill(0),fractions=Array(baseWidths.length).fill(0),usedShrink=0;for(let idx=0;idx<baseWidths.length;idx++){if(shrinkable[idx]<=0)continue;let exact=shrinkable[idx]/totalShrinkable*targetShrink,whole=Math.min(shrinkable[idx],Math.floor(exact));integerShrink[idx]=whole,fractions[idx]=exact-whole,usedShrink+=whole}let remainingShrink=targetShrink-usedShrink;while(remainingShrink>0){let bestIdx=-1,bestFraction=-1;for(let idx=0;idx<baseWidths.length;idx++){if(shrinkable[idx]-integerShrink[idx]<=0)continue;if(fractions[idx]>bestFraction)bestFraction=fractions[idx],bestIdx=idx}if(bestIdx===-1)break;integerShrink[bestIdx]+=1,fractions[bestIdx]=0,remainingShrink-=1}return baseWidths.map((width,idx)=>Math.max(floorWidths[idx],width-integerShrink[idx]))}fitColumnWidthsBalanced(widths,targetContentWidth){let minWidth=1+this.getHorizontalCellPadding(),hardMinWidths=Array(widths.length).fill(minWidth),baseWidths=widths.map((width)=>Math.max(1,Math.floor(width))),totalBaseWidth=baseWidths.reduce((sum,width)=>sum+width,0),columns=baseWidths.length;if(columns===0||totalBaseWidth<=targetContentWidth)return baseWidths;let evenShare=Math.max(minWidth,Math.floor(targetContentWidth/columns)),preferredMinWidths=baseWidths.map((width)=>Math.min(width,evenShare)),floorWidths=preferredMinWidths.reduce((sum,width)=>sum+width,0)<=targetContentWidth?preferredMinWidths:hardMinWidths,floorTotal=floorWidths.reduce((sum,width)=>sum+width,0),clampedTarget=Math.max(floorTotal,targetContentWidth);if(totalBaseWidth<=clampedTarget)return baseWidths;let shrinkable=baseWidths.map((width,idx)=>width-floorWidths[idx]);if(shrinkable.reduce((sum,value)=>sum+value,0)<=0)return[...floorWidths];let targetShrink=totalBaseWidth-clampedTarget,shrink=this.allocateShrinkByWeight(shrinkable,targetShrink,"sqrt");return baseWidths.map((width,idx)=>Math.max(floorWidths[idx],width-shrink[idx]))}allocateShrinkByWeight(shrinkable,targetShrink,mode){let shrink=Array(shrinkable.length).fill(0);if(targetShrink<=0)return shrink;let weights=shrinkable.map((value)=>{if(value<=0)return 0;return mode==="sqrt"?Math.sqrt(value):value}),totalWeight=weights.reduce((sum,value)=>sum+value,0);if(totalWeight<=0)return shrink;let fractions=Array(shrinkable.length).fill(0),usedShrink=0;for(let idx=0;idx<shrinkable.length;idx++){if(shrinkable[idx]<=0||weights[idx]<=0)continue;let exact=weights[idx]/totalWeight*targetShrink,whole=Math.min(shrinkable[idx],Math.floor(exact));shrink[idx]=whole,fractions[idx]=exact-whole,usedShrink+=whole}let remainingShrink=targetShrink-usedShrink;while(remainingShrink>0){let bestIdx=-1,bestFraction=-1;for(let idx=0;idx<shrinkable.length;idx++){if(shrinkable[idx]-shrink[idx]<=0)continue;if(bestIdx===-1||fractions[idx]>bestFraction||fractions[idx]===bestFraction&&shrinkable[idx]>shrinkable[bestIdx])bestIdx=idx,bestFraction=fractions[idx]}if(bestIdx===-1)break;shrink[bestIdx]+=1,fractions[bestIdx]=0,remainingShrink-=1}return shrink}computeRowHeights(columnWidths){let horizontalPadding=this.getHorizontalCellPadding(),verticalPadding=this.getVerticalCellPadding(),rowHeights=Array(this._rowCount).fill(1+verticalPadding);for(let rowIdx=0;rowIdx<this._rowCount;rowIdx++)for(let colIdx=0;colIdx<this._columnCount;colIdx++){let cell=this._cells[rowIdx]?.[colIdx];if(!cell)continue;let width=Math.max(1,(columnWidths[colIdx]??1)-horizontalPadding),measure=cell.textBufferView.measureForDimensions(width,MEASURE_HEIGHT),lineCount=Math.max(1,measure?.lineCount??1);rowHeights[rowIdx]=Math.max(rowHeights[rowIdx],lineCount+verticalPadding)}return rowHeights}computeOffsets(parts,startBoundary,endBoundary,includeInnerBoundaries,innerGap=0){let offsets=[startBoundary?0:-1],cursor=offsets[0]??0;for(let idx=0;idx<parts.length;idx++){let size=parts[idx]??1,separatorAfter=idx<parts.length-1?includeInnerBoundaries?1:innerGap:endBoundary?1:0;cursor+=size+separatorAfter,offsets.push(cursor)}return offsets}getInterColumnGap(borderLayout){if(borderLayout.innerVertical)return 0;return this._columnGap}getTotalInterColumnGap(borderLayout){return Math.max(0,this._columnCount-1)*this.getInterColumnGap(borderLayout)}applyLayoutToViews(layout){let horizontalPadding=this.getHorizontalCellPadding(),verticalPadding=this.getVerticalCellPadding();for(let rowIdx=0;rowIdx<this._rowCount;rowIdx++)for(let colIdx=0;colIdx<this._columnCount;colIdx++){let cell=this._cells[rowIdx]?.[colIdx];if(!cell)continue;let colWidth=layout.columnWidths[colIdx]??1,rowHeight=layout.rowHeights[rowIdx]??1,contentWidth=Math.max(1,colWidth-horizontalPadding),contentHeight=Math.max(1,rowHeight-verticalPadding);if(this._wrapMode==="none")cell.textBufferView.setWrapWidth(null);else cell.textBufferView.setWrapWidth(contentWidth);cell.textBufferView.setViewport(0,0,contentWidth,contentHeight)}}resolveBorderLayout(){return{left:this._outerBorder,right:this._outerBorder,top:this._outerBorder,bottom:this._outerBorder,innerVertical:this._border&&this._columnCount>1,innerHorizontal:this._border&&this._rowCount>1}}getVerticalBorderCount(borderLayout){return(borderLayout.left?1:0)+(borderLayout.right?1:0)+(borderLayout.innerVertical?Math.max(0,this._columnCount-1):0)}getHorizontalBorderCount(borderLayout){return(borderLayout.top?1:0)+(borderLayout.bottom?1:0)+(borderLayout.innerHorizontal?Math.max(0,this._rowCount-1):0)}drawBorders(buffer){if(!this._showBorders)return;let borderLayout=this.resolveBorderLayout();if(this.getVerticalBorderCount(borderLayout)===0&&this.getHorizontalBorderCount(borderLayout)===0)return;buffer.drawGrid({borderChars:BorderCharArrays[this._borderStyle],borderFg:this._borderColor,borderBg:this._borderBackgroundColor,columnOffsets:this._layout.columnOffsetsI32,rowOffsets:this._layout.rowOffsetsI32,drawInner:this._border,drawOuter:this._outerBorder})}drawCells(buffer){this.drawCellRange(buffer,0,this._rowCount-1)}drawCellRange(buffer,firstRow,lastRow){let colOffsets=this._layout.columnOffsets,rowOffsets=this._layout.rowOffsets,cellPaddingX=this._cellPaddingX,cellPaddingY=this._cellPaddingY;for(let rowIdx=firstRow;rowIdx<=lastRow;rowIdx++){let cellY=(rowOffsets[rowIdx]??0)+1+cellPaddingY;for(let colIdx=0;colIdx<this._columnCount;colIdx++){let cell=this._cells[rowIdx]?.[colIdx];if(!cell)continue;buffer.drawTextBuffer(cell.textBufferView,(colOffsets[colIdx]??0)+1+cellPaddingX,cellY)}}}redrawSelectionRows(firstRow,lastRow){if(firstRow>lastRow)return;if(this._backgroundColor.a<1){this.invalidateRasterOnly();return}let buffer=this.frameBuffer;if(!buffer)return;this.clearCellRange(buffer,firstRow,lastRow),this.drawCellRange(buffer,firstRow,lastRow),this.requestRender()}clearCellRange(buffer,firstRow,lastRow){let colWidths=this._layout.columnWidths,rowHeights=this._layout.rowHeights,colOffsets=this._layout.columnOffsets,rowOffsets=this._layout.rowOffsets;for(let rowIdx=firstRow;rowIdx<=lastRow;rowIdx++){let cellY=(rowOffsets[rowIdx]??0)+1,rowHeight=rowHeights[rowIdx]??1;for(let colIdx=0;colIdx<this._columnCount;colIdx++){let cellX=(colOffsets[colIdx]??0)+1,colWidth=colWidths[colIdx]??1;if(this._backgroundColor.a<1)for(let y2=cellY;y2<cellY+rowHeight;y2++)for(let x2=cellX;x2<cellX+colWidth;x2++)buffer.setCell(x2,y2," ",this._defaultFg,this._backgroundColor,this._defaultAttributes);else buffer.fillRect(cellX,cellY,colWidth,rowHeight,this._backgroundColor)}}}ensureLayoutReady(){if(!this._layoutDirty)return;this.rebuildLayoutForCurrentWidth()}getCellAtLocalPosition(localX,localY){if(this._rowCount===0||this._columnCount===0)return null;if(localX<0||localY<0||localX>=this._layout.tableWidth||localY>=this._layout.tableHeight)return null;let rowIdx=-1;for(let idx=0;idx<this._rowCount;idx++){let top=(this._layout.rowOffsets[idx]??0)+1,bottom=top+(this._layout.rowHeights[idx]??1)-1;if(localY>=top&&localY<=bottom){rowIdx=idx;break}}if(rowIdx<0)return null;let colIdx=-1;for(let idx=0;idx<this._columnCount;idx++){let left=(this._layout.columnOffsets[idx]??0)+1,right=left+(this._layout.columnWidths[idx]??1)-1;if(localX>=left&&localX<=right){colIdx=idx;break}}if(colIdx<0)return null;return{rowIdx,colIdx}}applySelectionToCells(localSelection,isStart){if(localSelection.anchorX===localSelection.focusX&&localSelection.anchorY===localSelection.focusY){this.resetCellSelections(),this._lastSelectionMode=null;return}let minSelY=Math.min(localSelection.anchorY,localSelection.focusY),maxSelY=Math.max(localSelection.anchorY,localSelection.focusY),firstRow=this.findRowForLocalY(minSelY),lastRow=this.findRowForLocalY(maxSelY),selection=this.resolveSelectionResolution(localSelection),modeChanged=this._lastSelectionMode!==selection.mode;this._lastSelectionMode=selection.mode;let lockToAnchorColumn=selection.mode==="column-locked"&&selection.anchorColumn!==null;for(let rowIdx=0;rowIdx<this._rowCount;rowIdx++){if(rowIdx<firstRow||rowIdx>lastRow){this.resetRowSelection(rowIdx);continue}let cellTop=(this._layout.rowOffsets[rowIdx]??0)+1+this._cellPaddingY;for(let colIdx=0;colIdx<this._columnCount;colIdx++){let cell=this._cells[rowIdx]?.[colIdx];if(!cell)continue;if(lockToAnchorColumn&&colIdx!==selection.anchorColumn){cell.textBufferView.resetLocalSelection();continue}let cellLeft=(this._layout.columnOffsets[colIdx]??0)+1+this._cellPaddingX,coords={anchorX:localSelection.anchorX-cellLeft,anchorY:localSelection.anchorY-cellTop,focusX:localSelection.focusX-cellLeft,focusY:localSelection.focusY-cellTop},isAnchorCell=selection.anchorCell!==null&&selection.anchorCell.rowIdx===rowIdx&&selection.anchorCell.colIdx===colIdx;if(selection.mode==="single-cell"&&!isAnchorCell){cell.textBufferView.resetLocalSelection();continue}let forceSet=isAnchorCell&&selection.mode!=="single-cell";if(forceSet)coords=this.getFullCellSelectionCoords(rowIdx,colIdx);if(isStart||modeChanged||forceSet)cell.textBufferView.setLocalSelection(coords.anchorX,coords.anchorY,coords.focusX,coords.focusY,this._selectionBg,this._selectionFg);else cell.textBufferView.updateLocalSelection(coords.anchorX,coords.anchorY,coords.focusX,coords.focusY,this._selectionBg,this._selectionFg)}}}resolveSelectionResolution(localSelection){let anchorCell=this.getCellAtLocalPosition(localSelection.anchorX,localSelection.anchorY),focusCell=this.getCellAtLocalPosition(localSelection.focusX,localSelection.focusY),anchorColumn=anchorCell?.colIdx??this.getColumnAtLocalX(localSelection.anchorX);if(anchorCell!==null&&focusCell!==null&&anchorCell.rowIdx===focusCell.rowIdx&&anchorCell.colIdx===focusCell.colIdx)return{mode:"single-cell",anchorCell,anchorColumn};let focusColumn=this.getColumnAtLocalX(localSelection.focusX);if(anchorColumn!==null&&focusColumn===anchorColumn)return{mode:"column-locked",anchorCell,anchorColumn};return{mode:"grid",anchorCell,anchorColumn}}getColumnAtLocalX(localX){if(this._columnCount===0)return null;if(localX<0||localX>=this._layout.tableWidth)return null;for(let colIdx=0;colIdx<this._columnCount;colIdx++){let colStart=(this._layout.columnOffsets[colIdx]??0)+1,colEnd=colStart+(this._layout.columnWidths[colIdx]??1)-1;if(localX>=colStart&&localX<=colEnd)return colIdx}return null}getFullCellSelectionCoords(rowIdx,colIdx){let colWidth=this._layout.columnWidths[colIdx]??1,rowHeight=this._layout.rowHeights[rowIdx]??1,contentWidth=Math.max(1,colWidth-this.getHorizontalCellPadding()),contentHeight=Math.max(1,rowHeight-this.getVerticalCellPadding());return{anchorX:-1,anchorY:0,focusX:contentWidth,focusY:contentHeight}}findRowForLocalY(localY){if(this._rowCount===0)return 0;if(localY<0)return 0;for(let rowIdx=0;rowIdx<this._rowCount;rowIdx++){let rowEnd=(this._layout.rowOffsets[rowIdx]??0)+1+(this._layout.rowHeights[rowIdx]??1)-1;if(localY<=rowEnd)return rowIdx}return this._rowCount-1}getSelectionRowRange(selection){if(!selection?.isActive||this._rowCount===0)return null;let minSelY=Math.min(selection.anchorY,selection.focusY),maxSelY=Math.max(selection.anchorY,selection.focusY);return{firstRow:this.findRowForLocalY(minSelY),lastRow:this.findRowForLocalY(maxSelY)}}getDirtySelectionRowRange(previousSelection,currentSelection){let previousRange=this.getSelectionRowRange(previousSelection),currentRange=this.getSelectionRowRange(currentSelection);if(previousRange===null)return currentRange;if(currentRange===null)return previousRange;return{firstRow:Math.min(previousRange.firstRow,currentRange.firstRow),lastRow:Math.max(previousRange.lastRow,currentRange.lastRow)}}resetRowSelection(rowIdx){let row=this._cells[rowIdx];if(!row)return;for(let cell of row)cell.textBufferView.resetLocalSelection()}resetCellSelections(){for(let rowIdx=0;rowIdx<this._rowCount;rowIdx++)this.resetRowSelection(rowIdx)}createEmptyLayout(){return{columnWidths:[],rowHeights:[],columnOffsets:[0],rowOffsets:[0],columnOffsetsI32:new Int32Array([0]),rowOffsetsI32:new Int32Array([0]),tableWidth:0,tableHeight:0}}resolveLayoutWidthConstraint(width){if(width===void 0||!Number.isFinite(width)||width<=0)return;if(this._wrapMode!=="none"||this.isFullWidthMode())return Math.max(1,Math.floor(width));return}getHorizontalCellPadding(){return this._cellPaddingX*2}getVerticalCellPadding(){return this._cellPaddingY*2}resolveColumnFitter(value){if(value===void 0)return this._defaultOptions.columnFitter;return value==="balanced"?"balanced":"proportional"}resolveCellPadding(value){if(value===void 0||!Number.isFinite(value))return this._defaultOptions.cellPadding;return Math.max(0,Math.floor(value))}resolveColumnGap(value){if(value===void 0||!Number.isFinite(value))return this._defaultOptions.columnGap;return Math.max(0,Math.floor(value))}invalidateLayoutAndRaster(markYogaDirty=!0){if(this._layoutDirty=!0,this._rasterDirty=!0,this._cachedMeasureLayout=null,this._cachedMeasureWidth=void 0,markYogaDirty)this.yogaNode.markDirty();this.requestRender()}invalidateRasterOnly(){this._rasterDirty=!0,this.requestRender()}}function parseMarkdownIncremental(newContent,prevState,trailingUnstable=2){if(!prevState||prevState.tokens.length===0)try{let tokens=x.lex(newContent,{gfm:!0});return{content:newContent,tokens,stableTokenCount:Math.max(0,tokens.length-trailingUnstable)}}catch{return{content:newContent,tokens:[],stableTokenCount:0}}let offset=0,reuseCount=0;for(let token of prevState.tokens){let tokenLength=token.raw.length;if(offset+tokenLength<=newContent.length&&newContent.startsWith(token.raw,offset))reuseCount++,offset+=tokenLength;else break}reuseCount=Math.max(0,reuseCount-trailingUnstable),offset=0;for(let i=0;i<reuseCount;i++)offset+=prevState.tokens[i].raw.length;let stableTokens=prevState.tokens.slice(0,reuseCount),remainingContent=newContent.slice(offset);if(!remainingContent)return{content:newContent,tokens:stableTokens,stableTokenCount:stableTokens.length};try{let newTokens=x.lex(remainingContent,{gfm:!0});return{content:newContent,tokens:[...stableTokens,...newTokens],stableTokenCount:trailingUnstable===0?stableTokens.length+newTokens.length:stableTokens.length}}catch{try{let fullTokens=x.lex(newContent,{gfm:!0});return{content:newContent,tokens:fullTokens,stableTokenCount:0}}catch{return{content:newContent,tokens:[],stableTokenCount:0}}}}var TRAILING_MARKDOWN_BLOCK_BREAKS_RE=/(?:\r?\n){2,}$/,TRAILING_MARKDOWN_BLOCK_NEWLINES_RE=/(?:\r?\n)+$/;function colorsEqual(left,right){if(!left||!right)return left===right;return left.equals(right)}class MarkdownRenderable extends Renderable{_content="";_syntaxStyle;_fg;_bg;_conceal;_concealCode;_treeSitterClient;_tableOptions;_renderNode;_internalBlockMode;_parseState=null;_streaming=!1;_blockStates=[];_stableBlockCount=0;_styleDirty=!1;_linkifyMarkdownChunks=(chunks,context)=>detectLinks(chunks,{content:context.content,highlights:context.highlights});_contentDefaultOptions={content:"",conceal:!0,concealCode:!1,streaming:!1,internalBlockMode:"coalesced"};constructor(ctx,options){super(ctx,{...options,flexDirection:"column",flexShrink:options.flexShrink??0});this._syntaxStyle=options.syntaxStyle,this._fg=options.fg?parseColor(options.fg):void 0,this._bg=options.bg?parseColor(options.bg):void 0,this._conceal=options.conceal??this._contentDefaultOptions.conceal,this._concealCode=options.concealCode??this._contentDefaultOptions.concealCode,this._content=options.content??this._contentDefaultOptions.content,this._treeSitterClient=options.treeSitterClient,this._tableOptions=options.tableOptions,this._renderNode=options.renderNode,this._streaming=options.streaming??this._contentDefaultOptions.streaming,this._internalBlockMode=options.internalBlockMode??this._contentDefaultOptions.internalBlockMode,this.updateBlocks()}get content(){return this._content}set content(value){if(this.isDestroyed)return;if(this._content!==value)this._content=value,this.updateBlocks(),this.requestRender()}get syntaxStyle(){return this._syntaxStyle}set syntaxStyle(value){if(this._syntaxStyle!==value)this._syntaxStyle=value,this._styleDirty=!0}get fg(){return this._fg}set fg(value){let next=value?parseColor(value):void 0;if(!colorsEqual(this._fg,next))this._fg=next,this._styleDirty=!0}get bg(){return this._bg}set bg(value){let next=value?parseColor(value):void 0;if(!colorsEqual(this._bg,next))this._bg=next,this._styleDirty=!0}get conceal(){return this._conceal}set conceal(value){if(this._conceal!==value)this._conceal=value,this._styleDirty=!0}get concealCode(){return this._concealCode}set concealCode(value){if(this._concealCode!==value)this._concealCode=value,this._styleDirty=!0}get streaming(){return this._streaming}set streaming(value){if(this.isDestroyed)return;if(this._streaming!==value)this._streaming=value,this.updateBlocks(!0)}get tableOptions(){return this._tableOptions}set tableOptions(value){this._tableOptions=value,this.applyTableOptionsToBlocks()}get renderNode(){return this._renderNode}set renderNode(value){if(this._renderNode===value)return;this._renderNode=value,this.clearBlockStates(),this._parseState=null,this.updateBlocks(!0),this.requestRender()}get internalBlockMode(){return this._internalBlockMode}set internalBlockMode(value){if(this._internalBlockMode===value)return;this._internalBlockMode=value,this.updateBlocks(!0),this.requestRender()}getStyle(group){if(!this._syntaxStyle)return;let style=this._syntaxStyle.getStyle(group);if(!style&&group.includes(".")){let baseName=group.split(".")[0];style=this._syntaxStyle.getStyle(baseName)}return style}createChunk(text,group,link2){let style=this.getStyle(group)||this.getStyle("default");return{__isChunk:!0,text,fg:style?.fg,bg:style?.bg,attributes:style?createTextAttributes({bold:style.bold,italic:style.italic,underline:style.underline,dim:style.dim}):0,link:link2}}createDefaultChunk(text){return this.createChunk(text,"default")}createInitialStyledText(token){if(!this._streaming)return;let chunks=[];if("tokens"in token&&Array.isArray(token.tokens))this.renderInlineContent(token.tokens,chunks);if(chunks.length===0&&"text"in token&&typeof token.text==="string")this.renderInlineContent(x.lexInline(token.text),chunks);return chunks.length>0?new StyledText(chunks):void 0}renderInlineContent(tokens,chunks){for(let token of tokens)this.renderInlineToken(token,chunks)}renderInlineToken(token,chunks){switch(token.type){case"text":chunks.push(this.createDefaultChunk(token.text));break;case"escape":chunks.push(this.createDefaultChunk(token.text));break;case"codespan":if(this._conceal)chunks.push(this.createChunk(token.text,"markup.raw"));else chunks.push(this.createChunk("`","markup.raw")),chunks.push(this.createChunk(token.text,"markup.raw")),chunks.push(this.createChunk("`","markup.raw"));break;case"strong":if(!this._conceal)chunks.push(this.createChunk("**","markup.strong"));for(let child of token.tokens)this.renderInlineTokenWithStyle(child,chunks,"markup.strong");if(!this._conceal)chunks.push(this.createChunk("**","markup.strong"));break;case"em":if(!this._conceal)chunks.push(this.createChunk("*","markup.italic"));for(let child of token.tokens)this.renderInlineTokenWithStyle(child,chunks,"markup.italic");if(!this._conceal)chunks.push(this.createChunk("*","markup.italic"));break;case"del":if(!this._conceal)chunks.push(this.createChunk("~~","markup.strikethrough"));for(let child of token.tokens)this.renderInlineTokenWithStyle(child,chunks,"markup.strikethrough");if(!this._conceal)chunks.push(this.createChunk("~~","markup.strikethrough"));break;case"link":{let linkHref={url:token.href};if(this._conceal){for(let child of token.tokens)this.renderInlineTokenWithStyle(child,chunks,"markup.link.label",linkHref);chunks.push(this.createChunk(" (","markup.link",linkHref)),chunks.push(this.createChunk(token.href,"markup.link.url",linkHref)),chunks.push(this.createChunk(")","markup.link",linkHref))}else{chunks.push(this.createChunk("[","markup.link",linkHref));for(let child of token.tokens)this.renderInlineTokenWithStyle(child,chunks,"markup.link.label",linkHref);chunks.push(this.createChunk("](","markup.link",linkHref)),chunks.push(this.createChunk(token.href,"markup.link.url",linkHref)),chunks.push(this.createChunk(")","markup.link",linkHref))}break}case"image":{let imageHref={url:token.href};if(this._conceal)chunks.push(this.createChunk(token.text||"image","markup.link.label",imageHref));else chunks.push(this.createChunk("),chunks.push(this.createChunk(token.href,"markup.link.url",imageHref)),chunks.push(this.createChunk(")","markup.link",imageHref));break}case"br":chunks.push(this.createDefaultChunk(`
|
|
3643
3643
|
`));break;default:if("tokens"in token&&Array.isArray(token.tokens))this.renderInlineContent(token.tokens,chunks);else if("text"in token&&typeof token.text==="string")chunks.push(this.createDefaultChunk(token.text));break}}renderInlineTokenWithStyle(token,chunks,styleGroup,link2){switch(token.type){case"text":chunks.push(this.createChunk(token.text,styleGroup,link2));break;case"escape":chunks.push(this.createChunk(token.text,styleGroup,link2));break;case"codespan":if(this._conceal)chunks.push(this.createChunk(token.text,"markup.raw",link2));else chunks.push(this.createChunk("`","markup.raw",link2)),chunks.push(this.createChunk(token.text,"markup.raw",link2)),chunks.push(this.createChunk("`","markup.raw",link2));break;default:this.renderInlineToken(token,chunks);break}}applyMargins(renderable,marginTop,marginBottom){renderable.marginTop=marginTop,renderable.marginBottom=marginBottom}createMarkdownCodeRenderable(content,id,marginBottom=0,onChunks=this._linkifyMarkdownChunks,baseHighlight,initialStyledText){return new CodeRenderable(this.ctx,{id,content,filetype:"markdown",syntaxStyle:this._syntaxStyle,fg:this._fg,bg:this._bg,conceal:this._conceal,drawUnstyledText:initialStyledText!==void 0,streaming:!0,initialStyledText,baseHighlight,onChunks,treeSitterClient:this._treeSitterClient,width:"100%",marginBottom})}getBlockquoteContent(token){return"text"in token&&typeof token.text==="string"&&token.text?token.text:" "}getBlockquoteBorderColor(){return this.getStyle("conceal")?.fg??this.getStyle("default")?.fg??this._fg??"#FFFFFF"}createBlockquoteRenderable(token,id,marginBottom=0){let renderable=new BoxRenderable(this.ctx,{id,width:"100%",border:["left"],borderColor:this.getBlockquoteBorderColor(),paddingLeft:1,flexShrink:0,marginBottom});return renderable.add(this.createMarkdownCodeRenderable(this.getBlockquoteContent(token),`${id}-content`,0,this._linkifyMarkdownChunks,"markup.quote")),renderable}createListRenderable(token,id,marginBottom=0){let list=new BoxRenderable(this.ctx,{id,width:"100%",flexDirection:"column",flexShrink:0,marginBottom});for(let item of this.getListItemInputs(token,id))list.add(this.createListItemRenderable(item));return list}getListItemInputs(token,id){let items=token.items??[],start=token.start===""||token.start===void 0||token.start===null?1:Number(token.start),markerWidth=Math.max(1,...items.map((_2,index)=>(token.ordered?`${start+index}.`:"-").length));return items.map((item,index)=>({item,marker:token.ordered?`${start+index}.`:"-",markerWidth,id:`${id}-item-${index}`}))}applyListRenderable(renderable,token,previousToken,id,marginBottom=0){if(!(renderable instanceof BoxRenderable))return!1;renderable.marginBottom=marginBottom;let inputs=this.getListItemInputs(token,id),previousItems=previousToken?.items??[],rows=renderable.getChildren();for(let index=0;index<inputs.length;index+=1){let input=inputs[index],existing=rows[index];if(existing instanceof BoxRenderable&&this.applyListItemRenderable(existing,input,previousItems[index]))continue;existing?.destroyRecursively(),renderable.add(this.createListItemRenderable(input),index)}for(let index=rows.length-1;index>=inputs.length;index-=1)rows[index]?.destroyRecursively();return!0}createListItemRenderable(input){let row=new BoxRenderable(this.ctx,{id:input.id,width:"100%",flexDirection:"row",flexShrink:0,marginBottom:/\n[ \t]*\n$/.test(input.item.raw)?1:0});row.add(new TextRenderable(this.ctx,{id:`${input.id}-marker`,content:new StyledText([this.createChunk(input.marker.padStart(input.markerWidth)+" ","markup.list")]),width:input.markerWidth+1,flexShrink:0}));let content=new BoxRenderable(this.ctx,{id:`${input.id}-content`,flexDirection:"column",flexGrow:1,flexShrink:1});row.add(content);let pendingMarginTop=0;for(let index=0;index<input.item.tokens.length;index+=1){let child=input.item.tokens[index];if(!child)continue;if(child.type==="checkbox")continue;if(child.type==="space"){pendingMarginTop=Math.max(pendingMarginTop,1);continue}let renderable=this.createListChildRenderable(child,`${input.id}-child-${index}`);if(!renderable)continue;renderable.marginTop=child.type==="list"?0:pendingMarginTop,pendingMarginTop=0,content.add(renderable)}return row}applyListItemRenderable(row,input,previousItem){this.applyListItemMarker(row,input);let content=row.getChildren()[1];if(!(content instanceof BoxRenderable))return!1;if(previousItem&&previousItem.raw===input.item.raw)return!0;return this.applyListItemChildren(content,input.item,previousItem,input.id)}applyListItemChildren(content,item,previousItem,id){let previousTokens=previousItem?this.getRenderableListItemTokens(previousItem):[],children=content.getChildren(),childIndex=0,pendingMarginTop=0;for(let tokenIndex=0;tokenIndex<item.tokens.length;tokenIndex+=1){let token=item.tokens[tokenIndex];if(!token)continue;if(token.type==="checkbox")continue;if(token.type==="space"){pendingMarginTop=Math.max(pendingMarginTop,1);continue}let existing=children[childIndex],childId=`${id}-child-${tokenIndex}`,marginTop=token.type==="list"?0:pendingMarginTop;if(pendingMarginTop=0,!existing){let renderable=this.createListChildRenderable(token,childId);if(!renderable)return!1;renderable.marginTop=marginTop,content.add(renderable,childIndex),childIndex+=1;continue}if(!this.applyListChildRenderable(existing,token,previousTokens[childIndex],childId))return!1;existing.marginTop=marginTop,childIndex+=1}return this.destroyListItemChildrenAfter(content,childIndex),!0}getRenderableListItemTokens(item){let tokens=[];for(let token of item.tokens){if(token.type==="checkbox"||token.type==="space")continue;tokens.push(token)}return tokens}applyListChildRenderable(renderable,token,previousToken,id){if((token.type==="text"||token.type==="paragraph")&&renderable instanceof CodeRenderable)return this.applyMarkdownCodeRenderable(renderable,this.normalizeScrollbackMarkdownBlockRaw(token.raw),0),!0;if(token.type==="list"&&renderable instanceof BoxRenderable)return this.applyListRenderable(renderable,token,previousToken,id);if(token.type==="code"&&renderable instanceof CodeRenderable)return this.applyCodeBlockRenderable(renderable,token,0),!0;return previousToken?.raw===token.raw}destroyListItemChildrenAfter(content,index){let children=content.getChildren();for(let i=children.length-1;i>=index;i-=1)children[i]?.destroyRecursively()}applyListItemMarker(row,input){let marker=row.getChildren()[0];if(!(marker instanceof TextRenderable))return;let marginBottom=/\n[ \t]*\n$/.test(input.item.raw)?1:0,markerWidth=input.markerWidth+1,markerText=input.marker.padStart(input.markerWidth)+" ";if(row.marginBottom!==marginBottom)row.marginBottom=marginBottom;if(marker.width!==markerWidth)marker.width=markerWidth;if(marker.chunks[0]?.text!==markerText)marker.content=new StyledText([this.createChunk(markerText,"markup.list")])}createListChildRenderable(token,id){if(token.type==="text"||token.type==="paragraph")return this.createMarkdownCodeRenderable(this.normalizeScrollbackMarkdownBlockRaw(token.raw),id,0,this._linkifyMarkdownChunks,void 0,this.createInitialStyledText(token));if(token.type==="list")return this.createListRenderable(token,id);if(token.type==="code")return this.createCodeRenderable(token,id);if(token.type==="blockquote")return this.createBlockquoteRenderable(token,id);if(token.type==="hr")return this.createHorizontalRuleRenderable(id);if(token.type==="table")return this.createTableBlock(token,id).renderable;return token.raw?this.createMarkdownCodeRenderable(token.raw,id,0,this._linkifyMarkdownChunks,void 0,this.createInitialStyledText(token)):null}createHorizontalRuleRenderable(id,marginBottom=0){return new BoxRenderable(this.ctx,{id,width:"100%",height:1,border:["top"],borderColor:this.getStyle("conceal")?.fg??this._fg??"#888888",flexShrink:0,marginBottom})}createCodeRenderable(token,id,marginBottom=0){return new CodeRenderable(this.ctx,{id,content:token.text,filetype:infoStringToFiletype(token.lang??""),syntaxStyle:this._syntaxStyle,fg:this._fg,bg:this._bg,conceal:this._concealCode,drawUnstyledText:!this._streaming,streaming:this._streaming,treeSitterClient:this._treeSitterClient,width:"100%",marginBottom})}applyMarkdownCodeRenderable(renderable,content,marginBottom,baseHighlight,initialStyledText){renderable.initialStyledText=initialStyledText,renderable.filetype="markdown",renderable.syntaxStyle=this._syntaxStyle,renderable.fg=this._fg,renderable.bg=this._bg,renderable.conceal=this._conceal,renderable.drawUnstyledText=initialStyledText!==void 0,renderable.streaming=!0,renderable.baseHighlight=baseHighlight,renderable.content=content,renderable.marginBottom=marginBottom}applyBlockquoteRenderable(renderable,token,marginBottom){if(!(renderable instanceof BoxRenderable))return;renderable.borderColor=this.getBlockquoteBorderColor(),renderable.marginBottom=marginBottom;let child=renderable.getChildren()[0];if(child instanceof CodeRenderable){this.applyMarkdownCodeRenderable(child,this.getBlockquoteContent(token),0,"markup.quote");return}for(let existing of renderable.getChildren())existing.destroyRecursively();renderable.add(this.createMarkdownCodeRenderable(this.getBlockquoteContent(token),`${renderable.id}-content`,0,this._linkifyMarkdownChunks,"markup.quote"))}applyCodeBlockRenderable(renderable,token,marginBottom){if(!(renderable instanceof CodeRenderable))return;renderable.filetype=infoStringToFiletype(token.lang??""),renderable.syntaxStyle=this._syntaxStyle,renderable.fg=this._fg,renderable.bg=this._bg,renderable.conceal=this._concealCode,renderable.drawUnstyledText=!this._streaming,renderable.streaming=this._streaming,renderable.content=token.text,renderable.marginBottom=marginBottom}shouldRenderSeparately(token){return token.type==="code"||token.type==="table"||token.type==="blockquote"||token.type==="hr"}getInterBlockMargin(token,nextToken){if(!nextToken)return 0;if(this.shouldRenderSeparately(token))return 1;if(!this.shouldRenderSeparately(nextToken))return 0;return TRAILING_MARKDOWN_BLOCK_NEWLINES_RE.test(token.raw)?0:1}applyInterBlockMargin(state,token,nextToken){if(state.tracksInterBlockMargin===!1)return;state.renderable.marginBottom=this.getInterBlockMargin(token,nextToken)}createMarkdownBlockToken(raw){return{type:"paragraph",raw,text:raw,tokens:[]}}normalizeMarkdownBlockRaw(raw){return raw.replace(TRAILING_MARKDOWN_BLOCK_BREAKS_RE,`
|
|
3644
3644
|
`)}normalizeScrollbackMarkdownBlockRaw(raw){return raw.replace(TRAILING_MARKDOWN_BLOCK_NEWLINES_RE,"")}isCodeBlockOnlyRenderer(){return this._renderNode?.codeBlockOnly===!0}buildRenderableTokens(tokens){if(this._renderNode&&!this.isCodeBlockOnlyRenderer())return tokens.filter((token)=>token.type!=="space");let renderTokens=[],markdownRaw="",flushMarkdownRaw=()=>{if(markdownRaw.length===0)return;let normalizedRaw=this.normalizeMarkdownBlockRaw(markdownRaw);if(normalizedRaw.length>0)renderTokens.push(this.createMarkdownBlockToken(normalizedRaw));markdownRaw=""};for(let i=0;i<tokens.length;i+=1){let token=tokens[i];if(token.type==="space"){if(markdownRaw.length===0)continue;let nextIndex=i+1;while(nextIndex<tokens.length&&tokens[nextIndex].type==="space")nextIndex+=1;let nextToken=tokens[nextIndex];if(nextToken&&!this.shouldRenderSeparately(nextToken))markdownRaw+=token.raw;continue}if(this.shouldRenderSeparately(token)){flushMarkdownRaw(),renderTokens.push(token);continue}markdownRaw+=token.raw}return flushMarkdownRaw(),renderTokens}buildTopLevelRenderBlocks(tokens){let blocks=[],gapBefore="";for(let i=0;i<tokens.length;i+=1){let token=tokens[i];if(token.type==="space"){gapBefore+=token.raw;continue}let prev=blocks[blocks.length-1],marginTop=prev&&this.shouldAddTopLevelMargin(prev.token,token,gapBefore)?1:0;blocks.push({token,sourceTokenEnd:i+1,marginTop}),gapBefore=""}return blocks}shouldAddTopLevelMargin(prev,current,gapBefore){if(this.isSeparatedTopLevelBlock(prev)||this.isSeparatedTopLevelBlock(current))return!0;if(prev.type!=="paragraph"||current.type!=="paragraph")return!1;return TRAILING_MARKDOWN_BLOCK_BREAKS_RE.test(prev.raw+gapBefore)}isSeparatedTopLevelBlock(token){return token.type==="heading"||token.type==="list"||this.shouldRenderSeparately(token)}getTableRowsToRender(table){return table.rows}hashString(value,seed){let hash=seed>>>0;for(let i=0;i<value.length;i+=1)hash^=value.charCodeAt(i),hash=Math.imul(hash,16777619);return hash>>>0}hashTableToken(token,seed,depth=0){let hash=this.hashString(token.type,seed);if("raw"in token&&typeof token.raw==="string")return this.hashString(token.raw,hash);if("text"in token&&typeof token.text==="string")hash=this.hashString(token.text,hash);if(depth<2&&"tokens"in token&&Array.isArray(token.tokens))for(let child of token.tokens)hash=this.hashTableToken(child,hash,depth+1);return hash>>>0}getTableCellKey(cell,isHeader){let seed=isHeader?2902232141:1371922141;if(!cell)return seed;if(typeof cell.text==="string")return this.hashString(cell.text,seed);if(Array.isArray(cell.tokens)&&cell.tokens.length>0){let hash=seed^cell.tokens.length;for(let token of cell.tokens)hash=this.hashTableToken(token,hash);return hash>>>0}return(seed^2654435769)>>>0}createTableDataCellChunks(cell){let chunks=[];if(cell)this.renderInlineContent(cell.tokens,chunks);return chunks.length>0?chunks:[this.createDefaultChunk(" ")]}createTableHeaderCellChunks(cell){let chunks=[];this.renderInlineContent(cell.tokens,chunks);let baseChunks=chunks.length>0?chunks:[this.createDefaultChunk(" ")],headingStyle=this.getStyle("markup.heading")||this.getStyle("default");if(!headingStyle)return baseChunks;let headingAttributes=createTextAttributes({bold:headingStyle.bold,italic:headingStyle.italic,underline:headingStyle.underline,dim:headingStyle.dim});return baseChunks.map((chunk)=>({...chunk,fg:headingStyle.fg??chunk.fg,bg:headingStyle.bg??chunk.bg,attributes:headingAttributes}))}buildTableContentCache(table,previous,forceRegenerate=!1){let colCount=table.header.length,rowsToRender=this.getTableRowsToRender(table);if(colCount===0||rowsToRender.length===0)return{cache:null,changed:previous!==void 0};let content=[],cellKeys=[],totalRows=rowsToRender.length+1,changed=forceRegenerate||!previous;for(let rowIndex=0;rowIndex<totalRows;rowIndex+=1){let rowContent=[],rowKeys=new Uint32Array(colCount);for(let colIndex=0;colIndex<colCount;colIndex+=1){let isHeader=rowIndex===0,cell=isHeader?table.header[colIndex]:rowsToRender[rowIndex-1]?.[colIndex],cellKey=this.getTableCellKey(cell,isHeader);rowKeys[colIndex]=cellKey;let previousCellKey=previous?.cellKeys[rowIndex]?.[colIndex],previousCellContent=previous?.content[rowIndex]?.[colIndex];if(!forceRegenerate&&previousCellKey===cellKey&&Array.isArray(previousCellContent)){rowContent.push(previousCellContent);continue}changed=!0,rowContent.push(isHeader?this.createTableHeaderCellChunks(table.header[colIndex]):this.createTableDataCellChunks(cell))}content.push(rowContent),cellKeys.push(rowKeys)}if(previous&&!changed){if(previous.content.length!==content.length)changed=!0;else for(let rowIndex=0;rowIndex<content.length;rowIndex+=1)if((previous.content[rowIndex]?.length??0)!==content[rowIndex].length){changed=!0;break}}return{cache:{content,cellKeys},changed}}resolveTableStyle(options=this._tableOptions){if(options?.style==="columns")return"columns";if(options?.style==="grid")return"grid";return this._internalBlockMode==="top-level"?"columns":"grid"}usesBorderlessColumnSpacing(options=this._tableOptions){let style=this.resolveTableStyle(options),borders=options?.borders??style==="grid";return style==="columns"&&!borders}resolveTableRenderableOptions(){let style=this.resolveTableStyle(),borders=this._tableOptions?.borders??style==="grid";return{columnWidthMode:this._tableOptions?.widthMode??(style==="columns"?"content":"full"),columnFitter:this._tableOptions?.columnFitter??"proportional",wrapMode:this._tableOptions?.wrapMode??"word",cellPadding:this._tableOptions?.cellPadding??0,cellPaddingX:this._tableOptions?.cellPaddingX??this._tableOptions?.cellPadding??0,cellPaddingY:this._tableOptions?.cellPaddingY??this._tableOptions?.cellPadding??0,columnGap:this.usesBorderlessColumnSpacing()?2:0,border:borders,outerBorder:this._tableOptions?.outerBorder??borders,showBorders:borders,borderStyle:this._tableOptions?.borderStyle??"single",borderColor:this._tableOptions?.borderColor??this.getStyle("conceal")?.fg??"#888888",selectable:this._tableOptions?.selectable??!0}}applyTableRenderableOptions(tableRenderable,options){tableRenderable.columnWidthMode=options.columnWidthMode,tableRenderable.columnFitter=options.columnFitter,tableRenderable.wrapMode=options.wrapMode,tableRenderable.cellPaddingX=options.cellPaddingX,tableRenderable.cellPaddingY=options.cellPaddingY,tableRenderable.columnGap=options.columnGap,tableRenderable.border=options.border,tableRenderable.outerBorder=options.outerBorder,tableRenderable.showBorders=options.showBorders,tableRenderable.borderStyle=options.borderStyle,tableRenderable.borderColor=options.borderColor,tableRenderable.selectable=options.selectable}applyTableOptionsToBlocks(){let options=this.resolveTableRenderableOptions(),updated=!1;for(let state of this._blockStates)if(state.renderable instanceof TextTableRenderable)this.applyTableRenderableOptions(state.renderable,options),updated=!0;if(updated)this.requestRender()}createTextTableRenderable(content,id,marginBottom=0){let options=this.resolveTableRenderableOptions();return new TextTableRenderable(this.ctx,{id,content,width:"100%",marginBottom,columnWidthMode:options.columnWidthMode,columnFitter:options.columnFitter,wrapMode:options.wrapMode,cellPadding:options.cellPadding,cellPaddingX:options.cellPaddingX,cellPaddingY:options.cellPaddingY,columnGap:options.columnGap,border:options.border,outerBorder:options.outerBorder,showBorders:options.showBorders,borderStyle:options.borderStyle,borderColor:options.borderColor,selectable:options.selectable})}createTableBlock(table,id,marginBottom=0,previousCache,forceRegenerate=!1){let{cache}=this.buildTableContentCache(table,previousCache,forceRegenerate);if(!cache)return{renderable:this.createMarkdownCodeRenderable(table.raw,id,marginBottom)};return{renderable:this.createTextTableRenderable(cache.content,id,marginBottom),tableContentCache:cache}}getStableBlockCount(blocks,stableTokenCount){if(this._internalBlockMode!=="top-level")return 0;let stableBlockCount=0;for(let block of blocks){if(block.sourceTokenEnd<=stableTokenCount){stableBlockCount+=1;continue}break}return stableBlockCount}syncTopLevelBlockState(state,block,tableContentCache=state.tableContentCache){state.token=block.token,state.tokenRaw=block.token.raw,state.marginTop=block.marginTop,state.tableContentCache=tableContentCache}getTopLevelBlockRaw(token){if(!token.raw)return;return this.shouldRenderSeparately(token)?token.raw:this.normalizeScrollbackMarkdownBlockRaw(token.raw)}createTopLevelDefaultRenderable(block,index){let{token,marginTop}=block,id=`${this.id}-block-${index}`;if(token.type==="code"){let renderable2=this.createCodeRenderable(token,id);return renderable2.marginTop=marginTop,{renderable:renderable2,canUpdateInPlace:!0}}if(token.type==="table"){let next=this.createTableBlock(token,id);return next.renderable.marginTop=marginTop,{...next,canUpdateInPlace:!0}}if(token.type==="blockquote"){let renderable2=this.createBlockquoteRenderable(token,id);return renderable2.marginTop=marginTop,{renderable:renderable2,canUpdateInPlace:!0}}if(token.type==="list"){let renderable2=this.createListRenderable(token,id);return renderable2.marginTop=marginTop,{renderable:renderable2,canUpdateInPlace:!0}}if(token.type==="hr"){let renderable2=this.createHorizontalRuleRenderable(id);return renderable2.marginTop=marginTop,{renderable:renderable2,canUpdateInPlace:!0}}let markdownRaw=this.getTopLevelBlockRaw(token);if(!markdownRaw)return{renderable:void 0,canUpdateInPlace:!0};let renderable=this.createMarkdownCodeRenderable(markdownRaw,id,0,this._linkifyMarkdownChunks,void 0,this.createInitialStyledText(token));return renderable.marginTop=marginTop,{renderable,canUpdateInPlace:!0}}createTopLevelRenderable(block,index){if(!this._renderNode)return this.createTopLevelDefaultRenderable(block,index);let custom=this.createTopLevelCustomRenderable(block,index);if(!custom.renderable)return this.createTopLevelDefaultRenderable(block,index);let marginTop=typeof custom.renderable.marginTop==="number"?Math.max(custom.renderable.marginTop,block.marginTop):block.marginTop;return this.applyMargins(custom.renderable,marginTop,0),{renderable:custom.renderable,tableContentCache:custom.tableContentCache,canUpdateInPlace:custom.canUpdateInPlace}}createDefaultRenderable(token,index,nextToken){let id=`${this.id}-block-${index}`,marginBottom=this.getInterBlockMargin(token,nextToken);if(token.type==="code")return this.createCodeRenderable(token,id,marginBottom);if(token.type==="blockquote")return this.createBlockquoteRenderable(token,id,marginBottom);if(token.type==="list")return this.createListRenderable(token,id,marginBottom);if(token.type==="hr")return this.createHorizontalRuleRenderable(id,marginBottom);if(token.type==="table")return this.createTableBlock(token,id,marginBottom).renderable;if(token.type==="space")return null;if(!token.raw)return null;return this.createMarkdownCodeRenderable(token.raw,id,marginBottom,this._linkifyMarkdownChunks,void 0,this.createInitialStyledText(token))}createCustomRenderable(token,index,nextToken){let custom=this.renderCustomNode(token,()=>{return{renderable:this.createDefaultRenderable(token,index,nextToken)}});if(!custom.renderable)return{tracksInterBlockMargin:!0,canUpdateInPlace:!0};let canUpdateInPlace=custom.renderable===custom.defaultResult?.renderable;return{renderable:custom.renderable,tracksInterBlockMargin:canUpdateInPlace,canUpdateInPlace}}createTopLevelCustomRenderable(block,index){let custom=this.renderCustomNode(block.token,()=>{return this.createTopLevelDefaultRenderable(block,index)});if(!custom.renderable)return{tracksInterBlockMargin:!0,canUpdateInPlace:!0};let canUpdateInPlace=custom.renderable===custom.defaultResult?.renderable;return{renderable:custom.renderable,tableContentCache:canUpdateInPlace?custom.defaultResult?.tableContentCache:void 0,tracksInterBlockMargin:canUpdateInPlace,canUpdateInPlace}}renderCustomNode(token,createDefault){if(!this._renderNode)return{};let defaultResult,custom=this._renderNode(token,{syntaxStyle:this._syntaxStyle,conceal:this._conceal,concealCode:this._concealCode,treeSitterClient:this._treeSitterClient,defaultRender:()=>{return defaultResult=createDefault(),defaultResult.renderable??null}});return this.destroyUnusedDefaultRenderable(defaultResult?.renderable,custom??void 0),custom?{renderable:custom,defaultResult}:{}}destroyUnusedDefaultRenderable(renderable,usedRenderable){if(!renderable||renderable===usedRenderable||renderable.parent)return;renderable.destroyRecursively()}updateBlockRenderable(state,token,index,nextToken,forceListRefresh=!1){let marginBottom=this.getInterBlockMargin(token,nextToken);if(token.type==="code"){this.applyCodeBlockRenderable(state.renderable,token,marginBottom);return}if(token.type==="blockquote"){this.applyBlockquoteRenderable(state.renderable,token,marginBottom);return}if(token.type==="list"){if(!this.applyListRenderable(state.renderable,token,forceListRefresh?void 0:state.token,`${this.id}-block-${index}`,marginBottom))state.renderable.destroyRecursively(),state.renderable=this.createListRenderable(token,`${this.id}-block-${index}`,marginBottom),this.add(state.renderable,index);return}if(token.type==="hr"){state.renderable.marginBottom=marginBottom;return}if(token.type==="table"){let tableToken=token,{cache,changed}=this.buildTableContentCache(tableToken,state.tableContentCache);if(!cache){if(state.renderable instanceof CodeRenderable){this.applyMarkdownCodeRenderable(state.renderable,tableToken.raw,marginBottom),state.tableContentCache=void 0;return}state.renderable.destroyRecursively();let fallbackRenderable=this.createMarkdownCodeRenderable(tableToken.raw,`${this.id}-block-${index}`,marginBottom);this.add(fallbackRenderable,index),state.renderable=fallbackRenderable,state.tableContentCache=void 0;return}if(state.renderable instanceof TextTableRenderable){if(changed)state.renderable.content=cache.content;this.applyTableRenderableOptions(state.renderable,this.resolveTableRenderableOptions()),state.renderable.marginBottom=marginBottom,state.tableContentCache=cache;return}state.renderable.destroyRecursively();let tableRenderable=this.createTextTableRenderable(cache.content,`${this.id}-block-${index}`,marginBottom);this.add(tableRenderable,index),state.renderable=tableRenderable,state.tableContentCache=cache;return}if(state.renderable instanceof CodeRenderable){this.applyMarkdownCodeRenderable(state.renderable,this.getTopLevelBlockRaw(token)??token.raw,marginBottom,void 0,this.createInitialStyledText(token));return}state.renderable.destroyRecursively();let markdownRenderable=this.createMarkdownCodeRenderable(this.getTopLevelBlockRaw(token)??token.raw,`${this.id}-block-${index}`,marginBottom,this._linkifyMarkdownChunks,void 0,this.createInitialStyledText(token));this.add(markdownRenderable,index),state.renderable=markdownRenderable}updateTopLevelBlocks(tokens,forceTableRefresh){let blocks=this.buildTopLevelRenderBlocks(tokens);this._stableBlockCount=this.getStableBlockCount(blocks,this._parseState?.stableTokenCount??0);let blockIndex=0;for(let i=0;i<blocks.length;i+=1){let block=blocks[i],existing=this._blockStates[blockIndex];if(existing&&existing.token===block.token&&!forceTableRefresh){if(existing.marginTop!==block.marginTop)this.applyMargins(existing.renderable,block.marginTop,0);this.syncTopLevelBlockState(existing,block),blockIndex++;continue}if(existing&&existing.tokenRaw===block.token.raw&&existing.token.type===block.token.type&&!forceTableRefresh){if(existing.marginTop!==block.marginTop)this.applyMargins(existing.renderable,block.marginTop,0);this.syncTopLevelBlockState(existing,block),blockIndex++;continue}if(existing&&!forceTableRefresh&&existing.canUpdateInPlace&&existing.token.type===block.token.type&&this.canUpdateBlockRenderable(existing.renderable,block.token)){if(this._renderNode){let custom=this.createTopLevelCustomRenderable(block,blockIndex);if(custom.renderable&&!custom.canUpdateInPlace){let marginTop=typeof custom.renderable.marginTop==="number"?Math.max(custom.renderable.marginTop,block.marginTop):block.marginTop;if(this.applyMargins(custom.renderable,marginTop,0),custom.renderable!==existing.renderable)existing.renderable.destroyRecursively(),this.add(custom.renderable,blockIndex);this._blockStates[blockIndex]={token:block.token,tokenRaw:block.token.raw,marginTop:block.marginTop,renderable:custom.renderable,tableContentCache:custom.tableContentCache,canUpdateInPlace:custom.canUpdateInPlace},blockIndex++;continue}this.destroyUnusedDefaultRenderable(custom.renderable)}if(this.updateBlockRenderable(existing,block.token,blockIndex,blocks[i+1]?.token),existing.renderable.marginBottom=0,existing.marginTop!==block.marginTop)this.applyMargins(existing.renderable,block.marginTop,0);this.syncTopLevelBlockState(existing,block),blockIndex++;continue}if(existing)existing.renderable.destroyRecursively();let next=this.createTopLevelRenderable(block,blockIndex);if(next.renderable)this.add(next.renderable,blockIndex),this._blockStates[blockIndex]={token:block.token,tokenRaw:block.token.raw,marginTop:block.marginTop,renderable:next.renderable,tableContentCache:next.tableContentCache,canUpdateInPlace:next.canUpdateInPlace};blockIndex++}while(this._blockStates.length>blockIndex)this._blockStates.pop().renderable.destroyRecursively()}canUpdateBlockRenderable(renderable,token){if(token.type==="code")return renderable instanceof CodeRenderable;if(token.type==="table")return renderable instanceof TextTableRenderable;if(token.type==="blockquote")return renderable instanceof BoxRenderable;if(token.type==="list")return renderable instanceof BoxRenderable;if(token.type==="hr")return renderable instanceof BoxRenderable;return renderable instanceof CodeRenderable}updateBlocks(forceTableRefresh=!1){if(this.isDestroyed)return;if(!this._content){this.clearBlockStates(),this._parseState=null,this._stableBlockCount=0;return}let trailingUnstable=this._streaming?2:0;this._parseState=parseMarkdownIncremental(this._content,this._parseState,trailingUnstable);let tokens=this._parseState.tokens;if(tokens.length===0&&this._content.length>0){this.clearBlockStates(),this._stableBlockCount=0;let fallback=this.createMarkdownCodeRenderable(this._content,`${this.id}-fallback`);this.add(fallback),this._blockStates=[{token:{type:"text",raw:this._content,text:this._content},tokenRaw:this._content,marginTop:0,renderable:fallback,tracksInterBlockMargin:!0,canUpdateInPlace:!0}];return}if(this._internalBlockMode==="top-level"){this.updateTopLevelBlocks(tokens,forceTableRefresh);return}this._stableBlockCount=0;let blockTokens=this.buildRenderableTokens(tokens),blockIndex=0;for(let i=0;i<blockTokens.length;i++){let token=blockTokens[i],nextToken=blockTokens[i+1],existing=this._blockStates[blockIndex],shouldForceRefresh=forceTableRefresh;if(existing&&existing.token===token){if(shouldForceRefresh)this.updateBlockRenderable(existing,token,blockIndex,nextToken),existing.tokenRaw=token.raw;else this.applyInterBlockMargin(existing,token,nextToken);blockIndex++;continue}if(existing&&existing.tokenRaw===token.raw&&existing.token.type===token.type){if(existing.token=token,shouldForceRefresh)this.updateBlockRenderable(existing,token,blockIndex,nextToken),existing.tokenRaw=token.raw;else this.applyInterBlockMargin(existing,token,nextToken);blockIndex++;continue}if(existing&&existing.canUpdateInPlace&&existing.token.type===token.type){let custom2=this.createCustomRenderable(token,blockIndex,nextToken);if(custom2.renderable&&!custom2.canUpdateInPlace){if(custom2.renderable!==existing.renderable)existing.renderable.destroyRecursively(),this.add(custom2.renderable,blockIndex);this._blockStates[blockIndex]={token,tokenRaw:token.raw,renderable:custom2.renderable,tracksInterBlockMargin:custom2.tracksInterBlockMargin,canUpdateInPlace:custom2.canUpdateInPlace},blockIndex++;continue}this.destroyUnusedDefaultRenderable(custom2.renderable),this.updateBlockRenderable(existing,token,blockIndex,nextToken),existing.token=token,existing.tokenRaw=token.raw,existing.tracksInterBlockMargin=!0,blockIndex++;continue}if(existing)existing.renderable.destroyRecursively();let renderable,tableContentCache,tracksInterBlockMargin=!0,canUpdateInPlace=!0,custom=this.createCustomRenderable(token,blockIndex,nextToken);if(custom.renderable)renderable=custom.renderable,tracksInterBlockMargin=custom.tracksInterBlockMargin,canUpdateInPlace=custom.canUpdateInPlace;if(!renderable)if(token.type==="table"){let tableBlock=this.createTableBlock(token,`${this.id}-block-${blockIndex}`,this.getInterBlockMargin(token,nextToken));renderable=tableBlock.renderable,tableContentCache=tableBlock.tableContentCache}else renderable=this.createDefaultRenderable(token,blockIndex,nextToken)??void 0;if(token.type==="table"&&!tableContentCache&&renderable instanceof TextTableRenderable){let{cache}=this.buildTableContentCache(token);tableContentCache=cache??void 0}if(renderable)this.add(renderable,blockIndex),this._blockStates[blockIndex]={token,tokenRaw:token.raw,renderable,tableContentCache,tracksInterBlockMargin,canUpdateInPlace};blockIndex++}while(this._blockStates.length>blockIndex)this._blockStates.pop().renderable.destroyRecursively()}clearBlockStates(){for(let state of this._blockStates)state.renderable.destroyRecursively();this._blockStates=[],this._stableBlockCount=0}rerenderBlocks(){if(this._internalBlockMode==="top-level"){this.updateBlocks(!0);return}for(let i=0;i<this._blockStates.length;i++){let state=this._blockStates[i],marginBottom=this.getInterBlockMargin(state.token,this._blockStates[i+1]?.token);if(state.token.type==="code"){this.applyCodeBlockRenderable(state.renderable,state.token,marginBottom);continue}if(state.token.type==="blockquote"){this.applyBlockquoteRenderable(state.renderable,state.token,marginBottom);continue}if(state.token.type==="list"){this.updateBlockRenderable(state,state.token,i,this._blockStates[i+1]?.token,!0);continue}if(state.token.type==="hr"){state.renderable.marginBottom=marginBottom;continue}if(state.token.type==="table"){let tableToken=state.token,{cache}=this.buildTableContentCache(tableToken,state.tableContentCache,!0);if(!cache){if(state.renderable instanceof CodeRenderable)this.applyMarkdownCodeRenderable(state.renderable,tableToken.raw,marginBottom);else{state.renderable.destroyRecursively();let fallbackRenderable=this.createMarkdownCodeRenderable(tableToken.raw,`${this.id}-block-${i}`,marginBottom);this.add(fallbackRenderable,i),state.renderable=fallbackRenderable}state.tableContentCache=void 0;continue}if(state.renderable instanceof TextTableRenderable){state.renderable.content=cache.content,this.applyTableRenderableOptions(state.renderable,this.resolveTableRenderableOptions()),state.renderable.marginBottom=marginBottom,state.tableContentCache=cache;continue}state.renderable.destroyRecursively();let tableRenderable=this.createTextTableRenderable(cache.content,`${this.id}-block-${i}`,marginBottom);this.add(tableRenderable,i),state.renderable=tableRenderable,state.tableContentCache=cache;continue}if(state.renderable instanceof CodeRenderable){this.applyMarkdownCodeRenderable(state.renderable,this.getTopLevelBlockRaw(state.token)??state.token.raw,marginBottom,void 0,this.createInitialStyledText(state.token));continue}state.renderable.destroyRecursively();let markdownRenderable=this.createMarkdownCodeRenderable(this.getTopLevelBlockRaw(state.token)??state.token.raw,`${this.id}-block-${i}`,marginBottom,this._linkifyMarkdownChunks,void 0,this.createInitialStyledText(state.token));this.add(markdownRenderable,i),state.renderable=markdownRenderable}}clearCache(){this._parseState=null,this.clearBlockStates(),this.updateBlocks(),this.requestRender()}refreshStyles(){this._styleDirty=!1,this.rerenderBlocks(),this.requestRender()}renderSelf(buffer,deltaTime){if(this._styleDirty)this._styleDirty=!1,this.rerenderBlocks();super.renderSelf(buffer,deltaTime)}}var defaultThumbBackgroundColor=RGBA.fromHex("#9a9ea3"),defaultTrackBackgroundColor=RGBA.fromHex("#252527");class SliderRenderable extends Renderable{orientation;_value;_min;_max;_viewPortSize;_backgroundColor;_foregroundColor;_onChange;constructor(ctx,options){super(ctx,{flexShrink:0,...options});this.orientation=options.orientation,this._min=options.min??0,this._max=options.max??100,this._value=options.value??this._min,this._viewPortSize=options.viewPortSize??Math.max(1,(this._max-this._min)*0.1),this._onChange=options.onChange,this._backgroundColor=options.backgroundColor?parseColor(options.backgroundColor):defaultTrackBackgroundColor,this._foregroundColor=options.foregroundColor?parseColor(options.foregroundColor):defaultThumbBackgroundColor,this.setupMouseHandling()}get value(){return this._value}set value(newValue){let clamped=Math.max(this._min,Math.min(this._max,newValue));if(clamped!==this._value)this._value=clamped,this._onChange?.(clamped),this.emit("change",{value:clamped}),this.requestRender()}get min(){return this._min}set min(newMin){if(newMin!==this._min){if(this._min=newMin,this._value<newMin)this.value=newMin;this.requestRender()}}get max(){return this._max}set max(newMax){if(newMax!==this._max){if(this._max=newMax,this._value>newMax)this.value=newMax;this.requestRender()}}set viewPortSize(size){let clampedSize=Math.max(0.01,Math.min(size,this._max-this._min));if(clampedSize!==this._viewPortSize)this._viewPortSize=clampedSize,this.requestRender()}get viewPortSize(){return this._viewPortSize}get backgroundColor(){return this._backgroundColor}set backgroundColor(value){this._backgroundColor=parseColor(value),this.requestRender()}get foregroundColor(){return this._foregroundColor}set foregroundColor(value){this._foregroundColor=parseColor(value),this.requestRender()}calculateDragOffsetVirtual(event){let trackStart=this.orientation==="vertical"?this.y:this.x,mousePos=(this.orientation==="vertical"?event.y:event.x)-trackStart,virtualMousePos=Math.max(0,Math.min((this.orientation==="vertical"?this.height:this.width)*2,mousePos*2)),virtualThumbStart=this.getVirtualThumbStart(),virtualThumbSize=this.getVirtualThumbSize();return Math.max(0,Math.min(virtualThumbSize,virtualMousePos-virtualThumbStart))}setupMouseHandling(){let isDragging=!1,dragOffsetVirtual=0;this.onMouseDown=(event)=>{event.stopPropagation(),event.preventDefault();let thumb=this.getThumbRect();if(event.x>=thumb.x&&event.x<thumb.x+thumb.width&&event.y>=thumb.y&&event.y<thumb.y+thumb.height)isDragging=!0,dragOffsetVirtual=this.calculateDragOffsetVirtual(event);else this.updateValueFromMouseDirect(event),isDragging=!0,dragOffsetVirtual=this.calculateDragOffsetVirtual(event)},this.onMouseDrag=(event)=>{if(!isDragging)return;event.stopPropagation(),this.updateValueFromMouseWithOffset(event,dragOffsetVirtual)},this.onMouseUp=(event)=>{if(isDragging)this.updateValueFromMouseWithOffset(event,dragOffsetVirtual);isDragging=!1}}updateValueFromMouseDirect(event){let trackStart=this.orientation==="vertical"?this.y:this.x,trackSize=this.orientation==="vertical"?this.height:this.width,relativeMousePos=(this.orientation==="vertical"?event.y:event.x)-trackStart,clampedMousePos=Math.max(0,Math.min(trackSize,relativeMousePos)),ratio=trackSize===0?0:clampedMousePos/trackSize,range=this._max-this._min,newValue=this._min+ratio*range;this.value=newValue}updateValueFromMouseWithOffset(event,offsetVirtual){let trackStart=this.orientation==="vertical"?this.y:this.x,trackSize=this.orientation==="vertical"?this.height:this.width,mousePos=this.orientation==="vertical"?event.y:event.x,virtualTrackSize=trackSize*2,relativeMousePos=mousePos-trackStart,virtualMousePos=Math.max(0,Math.min(trackSize,relativeMousePos))*2,virtualThumbSize=this.getVirtualThumbSize(),maxThumbStart=Math.max(0,virtualTrackSize-virtualThumbSize),desiredThumbStart=virtualMousePos-offsetVirtual;desiredThumbStart=Math.max(0,Math.min(maxThumbStart,desiredThumbStart));let ratio=maxThumbStart===0?0:desiredThumbStart/maxThumbStart,range=this._max-this._min,newValue=this._min+ratio*range;this.value=newValue}getThumbRect(){let virtualThumbSize=this.getVirtualThumbSize(),virtualThumbStart=this.getVirtualThumbStart(),realThumbStart=Math.floor(virtualThumbStart/2),realThumbSize=Math.ceil((virtualThumbStart+virtualThumbSize)/2)-realThumbStart;if(this.orientation==="vertical")return{x:this.x,y:this.y+realThumbStart,width:this.width,height:Math.max(1,realThumbSize)};else return{x:this.x+realThumbStart,y:this.y,width:Math.max(1,realThumbSize),height:this.height}}renderSelf(buffer){if(this.orientation==="horizontal")this.renderHorizontal(buffer);else this.renderVertical(buffer)}renderHorizontal(buffer){let virtualThumbSize=this.getVirtualThumbSize(),virtualThumbStart=this.getVirtualThumbStart(),virtualThumbEnd=virtualThumbStart+virtualThumbSize;buffer.fillRect(this.x,this.y,this.width,this.height,this._backgroundColor);let realStartCell=Math.floor(virtualThumbStart/2),realEndCell=Math.ceil(virtualThumbEnd/2)-1,startX=Math.max(0,realStartCell),endX=Math.min(this.width-1,realEndCell);for(let realX=startX;realX<=endX;realX++){let virtualCellStart=realX*2,virtualCellEnd=virtualCellStart+2,thumbStartInCell=Math.max(virtualThumbStart,virtualCellStart),coverage=Math.min(virtualThumbEnd,virtualCellEnd)-thumbStartInCell,char=" ";if(coverage>=2)char="\u2588";else if(thumbStartInCell===virtualCellStart)char="\u258C";else char="\u2590";for(let y2=0;y2<this.height;y2++)buffer.setCellWithAlphaBlending(this.x+realX,this.y+y2,char,this._foregroundColor,this._backgroundColor)}}renderVertical(buffer){let virtualThumbSize=this.getVirtualThumbSize(),virtualThumbStart=this.getVirtualThumbStart(),virtualThumbEnd=virtualThumbStart+virtualThumbSize;buffer.fillRect(this.x,this.y,this.width,this.height,this._backgroundColor);let realStartCell=Math.floor(virtualThumbStart/2),realEndCell=Math.ceil(virtualThumbEnd/2)-1,startY=Math.max(0,realStartCell),endY=Math.min(this.height-1,realEndCell);for(let realY=startY;realY<=endY;realY++){let virtualCellStart=realY*2,virtualCellEnd=virtualCellStart+2,thumbStartInCell=Math.max(virtualThumbStart,virtualCellStart),coverage=Math.min(virtualThumbEnd,virtualCellEnd)-thumbStartInCell,char=" ";if(coverage>=2)char="\u2588";else if(coverage>0)if(thumbStartInCell-virtualCellStart===0)char="\u2580";else char="\u2584";for(let x2=0;x2<this.width;x2++)buffer.setCellWithAlphaBlending(this.x+x2,this.y+realY,char,this._foregroundColor,this._backgroundColor)}}getVirtualThumbSize(){let virtualTrackSize=this.orientation==="vertical"?this.height*2:this.width*2,range=this._max-this._min;if(range===0)return virtualTrackSize;let viewportSize=Math.max(1,this._viewPortSize),contentSize=range+viewportSize;if(contentSize<=viewportSize)return virtualTrackSize;let thumbRatio=viewportSize/contentSize,calculatedSize=Math.floor(virtualTrackSize*thumbRatio);return Math.max(1,Math.min(calculatedSize,virtualTrackSize))}getVirtualThumbStart(){let virtualTrackSize=this.orientation==="vertical"?this.height*2:this.width*2,range=this._max-this._min;if(range===0)return 0;let valueRatio=(this._value-this._min)/range,virtualThumbSize=this.getVirtualThumbSize();return Math.round(valueRatio*(virtualTrackSize-virtualThumbSize))}}class ScrollBarRenderable extends Renderable{slider;startArrow;endArrow;orientation;_focusable=!0;_scrollSize=0;_scrollPosition=0;_viewportSize=0;_showArrows=!1;_manualVisibility=!1;_onChange;scrollStep=null;get visible(){return super.visible}set visible(value){this._manualVisibility=!0,super.visible=value}resetVisibilityControl(){this._manualVisibility=!1,this.recalculateVisibility()}get scrollSize(){return this._scrollSize}get scrollPosition(){return this._scrollPosition}get viewportSize(){return this._viewportSize}set scrollSize(value){if(value===this.scrollSize)return;this._scrollSize=value,this.recalculateVisibility(),this.updateSliderFromScrollState(),this.scrollPosition=this.scrollPosition}set scrollPosition(value){let newPosition=Math.round(Math.min(Math.max(0,value),this.scrollSize-this.viewportSize));if(newPosition!==this._scrollPosition)this._scrollPosition=newPosition,this.updateSliderFromScrollState()}set viewportSize(value){if(value===this.viewportSize)return;this._viewportSize=value,this.slider.viewPortSize=Math.max(1,this._viewportSize),this.recalculateVisibility(),this.updateSliderFromScrollState(),this.scrollPosition=this.scrollPosition}get showArrows(){return this._showArrows}set showArrows(value){if(value===this._showArrows)return;this._showArrows=value,this.startArrow.visible=value,this.endArrow.visible=value}constructor(ctx,{trackOptions,arrowOptions,orientation,showArrows=!1,...options}){super(ctx,{flexDirection:orientation==="vertical"?"column":"row",alignSelf:"stretch",alignItems:"stretch",...options});this._onChange=options.onChange,this.orientation=orientation,this._showArrows=showArrows;let scrollRange=Math.max(0,this._scrollSize-this._viewportSize),defaultStepSize=Math.max(1,this._viewportSize),stepSize=trackOptions?.viewPortSize??defaultStepSize;this.slider=new SliderRenderable(ctx,{orientation,min:0,max:scrollRange,value:this._scrollPosition,viewPortSize:stepSize,onChange:(value)=>{this._scrollPosition=Math.round(value),this._onChange?.(this._scrollPosition),this.emit("change",{position:this._scrollPosition})},...orientation==="vertical"?{width:Math.max(1,Math.min(2,this.width)),height:"100%",marginLeft:"auto"}:{width:"100%",height:1,marginTop:"auto"},flexGrow:1,flexShrink:1,...trackOptions}),this.updateSliderFromScrollState();let arrowOpts=arrowOptions?{foregroundColor:arrowOptions.backgroundColor,backgroundColor:arrowOptions.backgroundColor,attributes:arrowOptions.attributes,...arrowOptions}:{};this.startArrow=new ArrowRenderable(ctx,{alignSelf:"center",visible:this.showArrows,direction:this.orientation==="vertical"?"up":"left",height:this.orientation==="vertical"?1:1,...arrowOpts}),this.endArrow=new ArrowRenderable(ctx,{alignSelf:"center",visible:this.showArrows,direction:this.orientation==="vertical"?"down":"right",height:this.orientation==="vertical"?1:1,...arrowOpts}),this.add(this.startArrow),this.add(this.slider),this.add(this.endArrow);let startArrowMouseTimeout=void 0,endArrowMouseTimeout=void 0;this.startArrow.onMouseDown=(event)=>{event.stopPropagation(),event.preventDefault(),this.scrollBy(-0.5,"viewport"),startArrowMouseTimeout=setTimeout(()=>{this.scrollBy(-0.5,"viewport"),startArrowMouseTimeout=setInterval(()=>{this.scrollBy(-0.2,"viewport")},200)},500)},this.startArrow.onMouseUp=(event)=>{event.stopPropagation(),clearInterval(startArrowMouseTimeout)},this.endArrow.onMouseDown=(event)=>{event.stopPropagation(),event.preventDefault(),this.scrollBy(0.5,"viewport"),endArrowMouseTimeout=setTimeout(()=>{this.scrollBy(0.5,"viewport"),endArrowMouseTimeout=setInterval(()=>{this.scrollBy(0.2,"viewport")},200)},500)},this.endArrow.onMouseUp=(event)=>{event.stopPropagation(),clearInterval(endArrowMouseTimeout)}}set arrowOptions(options){Object.assign(this.startArrow,options),Object.assign(this.endArrow,options),this.requestRender()}set trackOptions(options){Object.assign(this.slider,options),this.requestRender()}updateSliderFromScrollState(){let scrollRange=Math.max(0,this._scrollSize-this._viewportSize);this.slider.min=0,this.slider.max=scrollRange,this.slider.value=Math.min(this._scrollPosition,scrollRange)}scrollBy(delta,unit="absolute"){let resolvedDelta=(unit==="viewport"?this.viewportSize:unit==="content"?this.scrollSize:unit==="step"?this.scrollStep??1:1)*delta;this.scrollPosition+=resolvedDelta}recalculateVisibility(){if(!this._manualVisibility){let sizeRatio=this.scrollSize<=this.viewportSize?1:this.viewportSize/this.scrollSize;super.visible=sizeRatio<1}}handleKeyPress(key){switch(key.name){case"left":case"h":if(this.orientation!=="horizontal")return!1;return this.scrollBy(-0.2,"viewport"),!0;case"right":case"l":if(this.orientation!=="horizontal")return!1;return this.scrollBy(0.2,"viewport"),!0;case"up":case"k":if(this.orientation!=="vertical")return!1;return this.scrollBy(-0.2,"viewport"),!0;case"down":case"j":if(this.orientation!=="vertical")return!1;return this.scrollBy(0.2,"viewport"),!0;case"pageup":return this.scrollBy(-0.5,"viewport"),!0;case"pagedown":return this.scrollBy(0.5,"viewport"),!0;case"home":return this.scrollBy(-1,"content"),!0;case"end":return this.scrollBy(1,"content"),!0}return!1}}class ArrowRenderable extends Renderable{_direction;_foregroundColor;_backgroundColor;_attributes;_arrowChars;constructor(ctx,options){super(ctx,options);if(this._direction=options.direction,this._foregroundColor=options.foregroundColor?parseColor(options.foregroundColor):RGBA.fromValues(1,1,1,1),this._backgroundColor=options.backgroundColor?parseColor(options.backgroundColor):RGBA.fromValues(0,0,0,0),this._attributes=options.attributes??0,this._arrowChars={up:"\u25B2",down:"\u25BC",left:"\u25C0",right:"\u25B6",...options.arrowChars},!options.width)this.width=stringWidth2(this.getArrowChar())}get direction(){return this._direction}set direction(value){if(this._direction!==value)this._direction=value,this.requestRender()}get foregroundColor(){return this._foregroundColor}set foregroundColor(value){if(this._foregroundColor!==value)this._foregroundColor=parseColor(value),this.requestRender()}get backgroundColor(){return this._backgroundColor}set backgroundColor(value){if(this._backgroundColor!==value)this._backgroundColor=parseColor(value),this.requestRender()}get attributes(){return this._attributes}set attributes(value){if(this._attributes!==value)this._attributes=value,this.requestRender()}set arrowChars(value){this._arrowChars={...this._arrowChars,...value},this.requestRender()}renderSelf(buffer){let char=this.getArrowChar();buffer.drawText(char,this.x,this.y,this._foregroundColor,this._backgroundColor,this._attributes)}getArrowChar(){switch(this._direction){case"up":return this._arrowChars.up;case"down":return this._arrowChars.down;case"left":return this._arrowChars.left;case"right":return this._arrowChars.right;default:return"?"}}}class ContentRenderable extends BoxRenderable{viewport;_viewportCulling;constructor(ctx,viewport,viewportCulling,options){super(ctx,options);this.viewport=viewport,this._viewportCulling=viewportCulling}get viewportCulling(){return this._viewportCulling}set viewportCulling(value){this._viewportCulling=value}_hasVisibleChildFilter(){return this._viewportCulling}_getVisibleChildren(){if(this._viewportCulling)return getObjectsInViewport({x:this.viewport.screenX,y:this.viewport.screenY,width:this.viewport.width,height:this.viewport.height},this.getChildrenSortedByPrimaryAxis(),this.primaryAxis,0).map((child)=>child.num);return super._getVisibleChildren()}}var SCROLLBOX_PADDING_KEYS=["padding","paddingX","paddingY","paddingTop","paddingRight","paddingBottom","paddingLeft"];function pickScrollBoxPadding(options){if(!options)return{};let picked={};for(let key of SCROLLBOX_PADDING_KEYS){let value=options[key];if(value!==void 0)picked[key]=value}return picked}function stripScrollBoxPadding(options){let sanitized={...options};for(let key of SCROLLBOX_PADDING_KEYS)delete sanitized[key];return sanitized}class ScrollBoxRenderable extends BoxRenderable{static idCounter=0;internalId=0;wrapper;viewport;content;horizontalScrollBar;verticalScrollBar;_focusable=!0;selectionListener;autoScrollMouseX=0;autoScrollMouseY=0;autoScrollThresholdVertical=3;autoScrollThresholdHorizontal=3;autoScrollSpeedSlow=6;autoScrollSpeedMedium=36;autoScrollSpeedFast=72;isAutoScrolling=!1;cachedAutoScrollSpeed=3;autoScrollAccumulatorX=0;autoScrollAccumulatorY=0;scrollAccumulatorX=0;scrollAccumulatorY=0;_stickyScroll;_stickyScrollTop=!1;_stickyScrollBottom=!1;_stickyScrollLeft=!1;_stickyScrollRight=!1;_stickyStart;_hasManualScroll=!1;_isApplyingStickyScroll=!1;scrollAccel;get stickyScroll(){return this._stickyScroll}set stickyScroll(value){this._stickyScroll=value,this.updateStickyState()}get stickyStart(){return this._stickyStart}set stickyStart(value){this._stickyStart=value,this.updateStickyState()}get scrollTop(){return this.verticalScrollBar.scrollPosition}set scrollTop(value){this.verticalScrollBar.scrollPosition=value,this.updateStickyState()}get scrollLeft(){return this.horizontalScrollBar.scrollPosition}set scrollLeft(value){this.horizontalScrollBar.scrollPosition=value,this.updateStickyState()}get scrollWidth(){return this.horizontalScrollBar.scrollSize}get scrollHeight(){return this.verticalScrollBar.scrollSize}updateStickyState(){if(!this._stickyScroll){this.syncManualScrollState();return}let maxScrollTop=Math.max(0,this.scrollHeight-this.viewport.height),maxScrollLeft=Math.max(0,this.scrollWidth-this.viewport.width);if(this.scrollTop<=0)this._stickyScrollTop=!0,this._stickyScrollBottom=!1;else if(this.scrollTop>=maxScrollTop)this._stickyScrollTop=!1,this._stickyScrollBottom=!0;else this._stickyScrollTop=!1,this._stickyScrollBottom=!1;if(this.scrollLeft<=0)this._stickyScrollLeft=!0,this._stickyScrollRight=!1;else if(this.scrollLeft>=maxScrollLeft)this._stickyScrollLeft=!1,this._stickyScrollRight=!0;else this._stickyScrollLeft=!1,this._stickyScrollRight=!1;this.syncManualScrollState()}syncManualScrollState(){if(!this._stickyScroll){this._hasManualScroll=!1;return}let maxScrollTop=Math.max(0,this.scrollHeight-this.viewport.height),maxScrollLeft=Math.max(0,this.scrollWidth-this.viewport.width),hasScrollableContent=maxScrollTop>1||maxScrollLeft>1;if(this._isApplyingStickyScroll){if(this._hasManualScroll&&hasScrollableContent&&this.isAtStickyPosition())this._hasManualScroll=!1;return}this._hasManualScroll=hasScrollableContent&&!this.isAtStickyPosition()}applyStickyStart(stickyStart){let wasApplyingStickyScroll=this._isApplyingStickyScroll;this._isApplyingStickyScroll=!0;try{switch(stickyStart){case"top":this._stickyScrollTop=!0,this._stickyScrollBottom=!1,this.verticalScrollBar.scrollPosition=0;break;case"bottom":this._stickyScrollTop=!1,this._stickyScrollBottom=!0,this.verticalScrollBar.scrollPosition=Math.max(0,this.scrollHeight-this.viewport.height);break;case"left":this._stickyScrollLeft=!0,this._stickyScrollRight=!1,this.horizontalScrollBar.scrollPosition=0;break;case"right":this._stickyScrollLeft=!1,this._stickyScrollRight=!0,this.horizontalScrollBar.scrollPosition=Math.max(0,this.scrollWidth-this.viewport.width);break}}finally{this._isApplyingStickyScroll=wasApplyingStickyScroll}}constructor(ctx,options){let{wrapperOptions,viewportOptions,contentOptions,rootOptions,scrollbarOptions,verticalScrollbarOptions,horizontalScrollbarOptions,stickyScroll=!1,stickyStart,scrollX=!1,scrollY=!0,scrollAcceleration,viewportCulling=!0,...rootBoxOptions}=options,forwardedContentPadding={...pickScrollBoxPadding(rootBoxOptions),...pickScrollBoxPadding(rootOptions)},sanitizedRootBoxOptions=stripScrollBoxPadding(rootBoxOptions),sanitizedRootOptions=rootOptions?stripScrollBoxPadding(rootOptions):void 0,mergedContentOptions={...forwardedContentPadding,...contentOptions};super(ctx,{flexDirection:"row",alignItems:"stretch",...sanitizedRootBoxOptions,...sanitizedRootOptions});if(this.internalId=ScrollBoxRenderable.idCounter++,this._stickyScroll=stickyScroll,this._stickyStart=stickyStart,this.scrollAccel=scrollAcceleration??new LinearScrollAccel,this.wrapper=new BoxRenderable(ctx,{flexDirection:"column",flexGrow:1,...wrapperOptions,id:`scroll-box-wrapper-${this.internalId}`}),super.add(this.wrapper),this.viewport=new BoxRenderable(ctx,{flexDirection:"column",flexGrow:1,overflow:"hidden",onSizeChange:()=>{this.recalculateBarProps()},...viewportOptions,id:`scroll-box-viewport-${this.internalId}`}),this.wrapper.add(this.viewport),this.content=new ContentRenderable(ctx,this.viewport,viewportCulling,{alignSelf:"flex-start",flexShrink:0,...scrollX?{minWidth:"100%"}:{minWidth:"100%",maxWidth:"100%"},...scrollY?{minHeight:"100%"}:{minHeight:"100%",maxHeight:"100%"},onSizeChange:()=>{this.recalculateBarProps()},...mergedContentOptions,id:`scroll-box-content-${this.internalId}`}),this.viewport.add(this.content),this.verticalScrollBar=new ScrollBarRenderable(ctx,{...scrollbarOptions,...verticalScrollbarOptions,arrowOptions:{...scrollbarOptions?.arrowOptions,...verticalScrollbarOptions?.arrowOptions},id:`scroll-box-vertical-scrollbar-${this.internalId}`,orientation:"vertical",onChange:(position)=>{this.content.translateY=-position,this.updateStickyState()}}),super.add(this.verticalScrollBar),this.horizontalScrollBar=new ScrollBarRenderable(ctx,{...scrollbarOptions,...horizontalScrollbarOptions,arrowOptions:{...scrollbarOptions?.arrowOptions,...horizontalScrollbarOptions?.arrowOptions},id:`scroll-box-horizontal-scrollbar-${this.internalId}`,orientation:"horizontal",onChange:(position)=>{this.content.translateX=-position,this.updateStickyState()}}),this.wrapper.add(this.horizontalScrollBar),this.recalculateBarProps(),stickyStart&&stickyScroll)this.applyStickyStart(stickyStart);this.selectionListener=()=>{let selection=this._ctx.getSelection();if(!selection||!selection.isDragging)this.stopAutoScroll()},this._ctx.on("selection",this.selectionListener)}onUpdate(deltaTime){this.handleAutoScroll(deltaTime)}scrollBy(delta,unit="absolute"){if(typeof delta==="number")this.verticalScrollBar.scrollBy(delta,unit);else this.verticalScrollBar.scrollBy(delta.y,unit),this.horizontalScrollBar.scrollBy(delta.x,unit)}scrollChildIntoView(childId){let child=this.content.findDescendantById(childId);if(!child)return;let getNearestDelta=(elementStart,elementEnd,viewportStart,viewportEnd)=>{let elementSize=elementEnd-elementStart,viewportSize=viewportEnd-viewportStart,elementStartOutside=elementStart<viewportStart,elementEndOutside=elementEnd>viewportEnd;if(elementStartOutside&&elementEndOutside)return 0;if(elementStartOutside&&elementSize<viewportSize||elementEndOutside&&elementSize>viewportSize)return elementStart-viewportStart;if(elementStartOutside&&elementSize>viewportSize||elementEndOutside&&elementSize<viewportSize)return elementEnd-viewportEnd;return 0},childTop=child.y,childBottom=child.y+child.height,viewportTop=this.viewport.y,viewportBottom=this.viewport.y+this.viewport.height,dy=getNearestDelta(childTop,childBottom,viewportTop,viewportBottom),childLeft=child.x,childRight=child.x+child.width,viewportLeft=this.viewport.x,viewportRight=this.viewport.x+this.viewport.width,dx=getNearestDelta(childLeft,childRight,viewportLeft,viewportRight);if(dx!==0||dy!==0)this.scrollBy({x:dx,y:dy})}scrollTo(position){if(typeof position==="number")this.scrollTop=position;else this.scrollTop=position.y,this.scrollLeft=position.x}isAtStickyPosition(){if(!this._stickyScroll||!this._stickyStart)return!1;let maxScrollTop=Math.max(0,this.scrollHeight-this.viewport.height),maxScrollLeft=Math.max(0,this.scrollWidth-this.viewport.width);switch(this._stickyStart){case"top":return this.scrollTop===0;case"bottom":return this.scrollTop>=maxScrollTop;case"left":return this.scrollLeft===0;case"right":return this.scrollLeft>=maxScrollLeft;default:return!1}}isAtStickyReengagePoint(stickyStart,maxScrollTop,maxScrollLeft){switch(stickyStart){case"top":return maxScrollTop>0&&this.scrollTop<=0;case"bottom":return maxScrollTop>0&&this.scrollTop>=maxScrollTop-1;case"left":return maxScrollLeft>0&&this.scrollLeft<=0;case"right":return maxScrollLeft>0&&this.scrollLeft>=maxScrollLeft-1}}add(obj,index){return this.content.add(obj,index)}insertBefore(obj,anchor){return this.content.insertBefore(obj,anchor)}remove(child){if(child.parent===this){super.remove(child);return}this.content.remove(child)}getChildren(){return this.content.getChildren()}getRenderable(id){return this.content.getRenderable(id)}onMouseEvent(event){if(event.type==="scroll"){let dir=event.scroll?.direction;if(event.modifiers.shift)dir=dir==="up"?"left":dir==="down"?"right":dir==="right"?"down":"up";let baseDelta=event.scroll?.delta??0,now=Date.now(),multiplier=this.scrollAccel.tick(now),scrollAmount=baseDelta*multiplier;if(dir==="up"){this.scrollAccumulatorY-=scrollAmount;let integerScroll=Math.trunc(this.scrollAccumulatorY);if(integerScroll!==0)this.scrollTop+=integerScroll,this.scrollAccumulatorY-=integerScroll}else if(dir==="down"){this.scrollAccumulatorY+=scrollAmount;let integerScroll=Math.trunc(this.scrollAccumulatorY);if(integerScroll!==0)this.scrollTop+=integerScroll,this.scrollAccumulatorY-=integerScroll}else if(dir==="left"){this.scrollAccumulatorX-=scrollAmount;let integerScroll=Math.trunc(this.scrollAccumulatorX);if(integerScroll!==0)this.scrollLeft+=integerScroll,this.scrollAccumulatorX-=integerScroll}else if(dir==="right"){this.scrollAccumulatorX+=scrollAmount;let integerScroll=Math.trunc(this.scrollAccumulatorX);if(integerScroll!==0)this.scrollLeft+=integerScroll,this.scrollAccumulatorX-=integerScroll}this.syncManualScrollState()}if(event.type==="drag"&&event.isDragging)this.updateAutoScroll(event.x,event.y);else if(event.type==="up")this.stopAutoScroll()}handleKeyPress(key){if(this.verticalScrollBar.handleKeyPress(key))return this.scrollAccel.reset(),this.resetScrollAccumulators(),this.syncManualScrollState(),!0;if(this.horizontalScrollBar.handleKeyPress(key))return this.scrollAccel.reset(),this.resetScrollAccumulators(),this.syncManualScrollState(),!0;return!1}resetScrollAccumulators(){this.scrollAccumulatorX=0,this.scrollAccumulatorY=0}startAutoScroll(mouseX,mouseY){if(this.stopAutoScroll(),this.autoScrollMouseX=mouseX,this.autoScrollMouseY=mouseY,this.cachedAutoScrollSpeed=this.getAutoScrollSpeed(mouseX,mouseY),this.isAutoScrolling=!0,!this.live)this.live=!0}updateAutoScroll(mouseX,mouseY){this.autoScrollMouseX=mouseX,this.autoScrollMouseY=mouseY,this.cachedAutoScrollSpeed=this.getAutoScrollSpeed(mouseX,mouseY);let scrollX=this.getAutoScrollDirectionX(mouseX),scrollY=this.getAutoScrollDirectionY(mouseY);if(scrollX===0&&scrollY===0)this.stopAutoScroll();else if(!this.isAutoScrolling)this.startAutoScroll(mouseX,mouseY)}stopAutoScroll(){let wasAutoScrolling=this.isAutoScrolling;if(this.isAutoScrolling=!1,this.autoScrollAccumulatorX=0,this.autoScrollAccumulatorY=0,wasAutoScrolling&&!this.hasOtherLiveReasons())this.live=!1}hasOtherLiveReasons(){return!1}handleAutoScroll(deltaTime){if(!this.isAutoScrolling)return;let scrollX=this.getAutoScrollDirectionX(this.autoScrollMouseX),scrollY=this.getAutoScrollDirectionY(this.autoScrollMouseY),scrollAmount=this.cachedAutoScrollSpeed*(deltaTime/1000),scrolled=!1;if(scrollX!==0){this.autoScrollAccumulatorX+=scrollX*scrollAmount;let integerScrollX=Math.trunc(this.autoScrollAccumulatorX);if(integerScrollX!==0)this.scrollLeft+=integerScrollX,this.autoScrollAccumulatorX-=integerScrollX,scrolled=!0}if(scrollY!==0){this.autoScrollAccumulatorY+=scrollY*scrollAmount;let integerScrollY=Math.trunc(this.autoScrollAccumulatorY);if(integerScrollY!==0)this.scrollTop+=integerScrollY,this.autoScrollAccumulatorY-=integerScrollY,scrolled=!0}if(scrolled)this._ctx.requestSelectionUpdate();if(scrollX===0&&scrollY===0)this.stopAutoScroll()}getAutoScrollDirectionX(mouseX){let relativeX=mouseX-this.x,distToLeft=relativeX,distToRight=this.width-relativeX;if(distToLeft<=this.autoScrollThresholdHorizontal)return this.scrollLeft>0?-1:0;else if(distToRight<=this.autoScrollThresholdHorizontal){let maxScrollLeft=this.scrollWidth-this.viewport.width;return this.scrollLeft<maxScrollLeft?1:0}return 0}getAutoScrollDirectionY(mouseY){let relativeY=mouseY-this.y,distToTop=relativeY,distToBottom=this.height-relativeY;if(distToTop<=this.autoScrollThresholdVertical)return this.scrollTop>0?-1:0;else if(distToBottom<=this.autoScrollThresholdVertical){let maxScrollTop=this.scrollHeight-this.viewport.height;return this.scrollTop<maxScrollTop?1:0}return 0}getAutoScrollSpeed(mouseX,mouseY){let relativeX=mouseX-this.x,relativeY=mouseY-this.y,distToLeft=relativeX,distToRight=this.width-relativeX,distToTop=relativeY,distToBottom=this.height-relativeY,minDistance=Math.min(distToLeft,distToRight,distToTop,distToBottom);if(minDistance<=1)return this.autoScrollSpeedFast;else if(minDistance<=2)return this.autoScrollSpeedMedium;else return this.autoScrollSpeedSlow}recalculateBarProps(){let wasApplyingStickyScroll=this._isApplyingStickyScroll;this._isApplyingStickyScroll=!0;try{if(this.verticalScrollBar.scrollSize=this.content.height,this.verticalScrollBar.viewportSize=this.viewport.height,this.horizontalScrollBar.scrollSize=this.content.width,this.horizontalScrollBar.viewportSize=this.viewport.width,this._stickyScroll){let newMaxScrollTop=Math.max(0,this.scrollHeight-this.viewport.height),newMaxScrollLeft=Math.max(0,this.scrollWidth-this.viewport.width),stickyStart=this._stickyStart;if(stickyStart&&!this._hasManualScroll)this.applyStickyStart(stickyStart);else if(stickyStart&&this._hasManualScroll&&this.isAtStickyReengagePoint(stickyStart,newMaxScrollTop,newMaxScrollLeft))this._hasManualScroll=!1,this.applyStickyStart(stickyStart);else if(!this._hasManualScroll){if(this._stickyScrollTop)this.scrollTop=0;else if(this._stickyScrollBottom&&newMaxScrollTop>0)this.scrollTop=newMaxScrollTop;if(this._stickyScrollLeft)this.scrollLeft=0;else if(this._stickyScrollRight&&newMaxScrollLeft>0)this.scrollLeft=newMaxScrollLeft}}}finally{this._isApplyingStickyScroll=wasApplyingStickyScroll}process.nextTick(()=>{this.requestRender()})}set padding(value){this.content.padding=value,this.requestRender()}set paddingX(value){this.content.paddingX=value,this.requestRender()}set paddingY(value){this.content.paddingY=value,this.requestRender()}set paddingTop(value){this.content.paddingTop=value,this.requestRender()}set paddingRight(value){this.content.paddingRight=value,this.requestRender()}set paddingBottom(value){this.content.paddingBottom=value,this.requestRender()}set paddingLeft(value){this.content.paddingLeft=value,this.requestRender()}set rootOptions(options){Object.assign(this,options),this.requestRender()}set wrapperOptions(options){Object.assign(this.wrapper,options),this.requestRender()}set viewportOptions(options){Object.assign(this.viewport,options),this.requestRender()}set contentOptions(options){Object.assign(this.content,options),this.requestRender()}set scrollbarOptions(options){Object.assign(this.verticalScrollBar,options),Object.assign(this.horizontalScrollBar,options),this.requestRender()}set verticalScrollbarOptions(options){Object.assign(this.verticalScrollBar,options),this.requestRender()}set horizontalScrollbarOptions(options){Object.assign(this.horizontalScrollBar,options),this.requestRender()}get scrollAcceleration(){return this.scrollAccel}set scrollAcceleration(value){this.scrollAccel=value}get viewportCulling(){return this.content.viewportCulling}set viewportCulling(value){this.content.viewportCulling=value,this.requestRender()}destroySelf(){if(this.selectionListener)this._ctx.off("selection",this.selectionListener),this.selectionListener=void 0;super.destroySelf()}}var defaultSelectKeybindings=[{name:"up",action:"move-up"},{name:"k",action:"move-up"},{name:"down",action:"move-down"},{name:"j",action:"move-down"},{name:"up",shift:!0,action:"move-up-fast"},{name:"down",shift:!0,action:"move-down-fast"},{name:"return",action:"select-current"},{name:"linefeed",action:"select-current"}],SelectRenderableEvents;((SelectRenderableEvents2)=>{SelectRenderableEvents2.SELECTION_CHANGED="selectionChanged",SelectRenderableEvents2.ITEM_SELECTED="itemSelected"})(SelectRenderableEvents||={});class SelectRenderable extends Renderable{_focusable=!0;_options=[];_selectedIndex=0;scrollOffset=0;maxVisibleItems;_backgroundColor;_textColor;_focusedBackgroundColor;_focusedTextColor;_selectedBackgroundColor;_selectedTextColor;_descriptionColor;_selectedDescriptionColor;_showScrollIndicator;_wrapSelection;_showDescription;_showSelectionIndicator;_font;_itemSpacing;linesPerItem;fontHeight;_fastScrollStep;_keyBindingsMap;_keyAliasMap;_keyBindings;_defaultOptions={backgroundColor:"transparent",textColor:"#FFFFFF",focusedBackgroundColor:"#1a1a1a",focusedTextColor:"#FFFFFF",selectedBackgroundColor:"#334455",selectedTextColor:"#FFFF00",selectedIndex:0,descriptionColor:"#888888",selectedDescriptionColor:"#CCCCCC",showScrollIndicator:!1,wrapSelection:!1,showDescription:!0,showSelectionIndicator:!0,itemSpacing:0,fastScrollStep:5};constructor(ctx,options){super(ctx,{...options,buffered:!0});this._options=options.options||[];let requestedIndex=options.selectedIndex??this._defaultOptions.selectedIndex;this._selectedIndex=this._options.length>0?Math.min(requestedIndex,this._options.length-1):0,this._backgroundColor=parseColor(options.backgroundColor||this._defaultOptions.backgroundColor),this._textColor=parseColor(options.textColor||this._defaultOptions.textColor),this._focusedBackgroundColor=parseColor(options.focusedBackgroundColor||this._defaultOptions.focusedBackgroundColor),this._focusedTextColor=parseColor(options.focusedTextColor||this._defaultOptions.focusedTextColor),this._showScrollIndicator=options.showScrollIndicator??this._defaultOptions.showScrollIndicator,this._wrapSelection=options.wrapSelection??this._defaultOptions.wrapSelection,this._showDescription=options.showDescription??this._defaultOptions.showDescription,this._showSelectionIndicator=options.showSelectionIndicator??this._defaultOptions.showSelectionIndicator,this._font=options.font,this._itemSpacing=options.itemSpacing||this._defaultOptions.itemSpacing,this.fontHeight=this._font?measureText({text:"A",font:this._font}).height:1,this.linesPerItem=this._showDescription?this._font?this.fontHeight+1:2:this._font?this.fontHeight:1,this.linesPerItem+=this._itemSpacing,this.maxVisibleItems=Math.max(1,Math.floor(this.height/this.linesPerItem)),this._selectedBackgroundColor=parseColor(options.selectedBackgroundColor||this._defaultOptions.selectedBackgroundColor),this._selectedTextColor=parseColor(options.selectedTextColor||this._defaultOptions.selectedTextColor),this._descriptionColor=parseColor(options.descriptionColor||this._defaultOptions.descriptionColor),this._selectedDescriptionColor=parseColor(options.selectedDescriptionColor||this._defaultOptions.selectedDescriptionColor),this._fastScrollStep=options.fastScrollStep||this._defaultOptions.fastScrollStep,this._keyAliasMap=mergeKeyAliases(defaultKeyAliases,options.keyAliasMap||{}),this._keyBindings=options.keyBindings||[];let mergedBindings=mergeKeyBindings(defaultSelectKeybindings,this._keyBindings);this._keyBindingsMap=buildKeyBindingsMap(mergedBindings,this._keyAliasMap),this.updateScrollOffset(),this.requestRender()}renderSelf(buffer,deltaTime){if(!this.visible||!this.frameBuffer)return;if(this.isDirty)this.refreshFrameBuffer()}refreshFrameBuffer(){if(!this.frameBuffer)return;let bgColor=this._focused?this._focusedBackgroundColor:this._backgroundColor;if(this.frameBuffer.clear(bgColor),this._options.length===0)return;let contentX=0,contentY=0,contentWidth=this.width,contentHeight=this.height,visibleOptions=this._options.slice(this.scrollOffset,this.scrollOffset+this.maxVisibleItems);for(let i=0;i<visibleOptions.length;i++){let actualIndex=this.scrollOffset+i,option=visibleOptions[i],isSelected=actualIndex===this._selectedIndex,itemY=contentY+i*this.linesPerItem;if(itemY+this.linesPerItem-1>=contentY+contentHeight)break;if(isSelected){let contentHeight2=this.linesPerItem-this._itemSpacing;this.frameBuffer.fillRect(contentX,itemY,contentWidth,contentHeight2,this._selectedBackgroundColor)}let indicator=this._showSelectionIndicator?isSelected?"\u25B6 ":" ":"",indicatorWidth=this._showSelectionIndicator?2:0,nameContent=`${indicator}${option.name}`,baseTextColor=this._focused?this._focusedTextColor:this._textColor,nameColor=isSelected?this._selectedTextColor:baseTextColor,textX=contentX+1+indicatorWidth;if(this._font){if(indicator)this.frameBuffer.drawText(indicator,contentX+1,itemY,nameColor);renderFontToFrameBuffer(this.frameBuffer,{text:option.name,x:textX,y:itemY,color:nameColor,backgroundColor:isSelected?this._selectedBackgroundColor:bgColor,font:this._font})}else this.frameBuffer.drawText(nameContent,contentX+1,itemY,nameColor);if(this._showDescription&&itemY+this.fontHeight<contentY+contentHeight){let descColor=isSelected?this._selectedDescriptionColor:this._descriptionColor;this.frameBuffer.drawText(option.description,textX,itemY+this.fontHeight,descColor)}}if(this._showScrollIndicator&&this._options.length>this.maxVisibleItems)this.renderScrollIndicatorToFrameBuffer(contentX,contentY,contentWidth,contentHeight)}renderScrollIndicatorToFrameBuffer(contentX,contentY,contentWidth,contentHeight){if(!this.frameBuffer)return;let maxScrollOffset=this._options.length-this.maxVisibleItems,scrollPercent=this.scrollOffset/maxScrollOffset,indicatorHeight=Math.max(1,contentHeight-2),indicatorY=contentY+1+Math.floor(scrollPercent*indicatorHeight),indicatorX=contentX+contentWidth-1;this.frameBuffer.drawText("\u2588",indicatorX,indicatorY,parseColor("#666666"))}get options(){return this._options}set options(options){this._options=options,this._selectedIndex=Math.min(this._selectedIndex,Math.max(0,options.length-1)),this.updateScrollOffset(),this.requestRender()}getSelectedOption(){return this._options[this._selectedIndex]||null}getSelectedIndex(){return this._selectedIndex}moveUp(steps=1){let newIndex=this._selectedIndex-steps;if(newIndex>=0)this._selectedIndex=newIndex;else if(this._wrapSelection&&this._options.length>0)this._selectedIndex=this._options.length-1;else this._selectedIndex=0;this.updateScrollOffset(),this.requestRender(),this.emit("selectionChanged",this._selectedIndex,this.getSelectedOption())}moveDown(steps=1){let newIndex=this._selectedIndex+steps;if(newIndex<this._options.length)this._selectedIndex=newIndex;else if(this._wrapSelection&&this._options.length>0)this._selectedIndex=0;else this._selectedIndex=this._options.length-1;this.updateScrollOffset(),this.requestRender(),this.emit("selectionChanged",this._selectedIndex,this.getSelectedOption())}selectCurrent(){let selected=this.getSelectedOption();if(selected)this.emit("itemSelected",this._selectedIndex,selected)}setSelectedIndex(index){if(index>=0&&index<this._options.length)this._selectedIndex=index,this.updateScrollOffset(),this.requestRender(),this.emit("selectionChanged",this._selectedIndex,this.getSelectedOption())}updateScrollOffset(){if(!this._options)return;let halfVisible=Math.floor(this.maxVisibleItems/2),newScrollOffset=Math.max(0,Math.min(this._selectedIndex-halfVisible,this._options.length-this.maxVisibleItems));if(newScrollOffset!==this.scrollOffset)this.scrollOffset=newScrollOffset,this.requestRender()}onResize(width,height){this.maxVisibleItems=Math.max(1,Math.floor(height/this.linesPerItem)),this.updateScrollOffset(),this.requestRender()}handleKeyPress(key){let action=getKeyBindingAction(this._keyBindingsMap,key);if(action)switch(action){case"move-up":return this.moveUp(1),!0;case"move-down":return this.moveDown(1),!0;case"move-up-fast":return this.moveUp(this._fastScrollStep),!0;case"move-down-fast":return this.moveDown(this._fastScrollStep),!0;case"select-current":return this.selectCurrent(),!0}return!1}get showScrollIndicator(){return this._showScrollIndicator}set showScrollIndicator(show){this._showScrollIndicator=show,this.requestRender()}get showDescription(){return this._showDescription}set showDescription(show){if(this._showDescription!==show)this._showDescription=show,this.linesPerItem=this._showDescription?this._font?this.fontHeight+1:2:this._font?this.fontHeight:1,this.linesPerItem+=this._itemSpacing,this.maxVisibleItems=Math.max(1,Math.floor(this.height/this.linesPerItem)),this.updateScrollOffset(),this.requestRender()}get showSelectionIndicator(){return this._showSelectionIndicator}set showSelectionIndicator(show){let next=show??this._defaultOptions.showSelectionIndicator;if(this._showSelectionIndicator!==next)this._showSelectionIndicator=next,this.requestRender()}get wrapSelection(){return this._wrapSelection}set wrapSelection(wrap){this._wrapSelection=wrap}set backgroundColor(value){let newColor=parseColor(value??this._defaultOptions.backgroundColor);if(this._backgroundColor!==newColor)this._backgroundColor=newColor,this.requestRender()}set textColor(value){let newColor=parseColor(value??this._defaultOptions.textColor);if(this._textColor!==newColor)this._textColor=newColor,this.requestRender()}set focusedBackgroundColor(value){let newColor=parseColor(value??this._defaultOptions.focusedBackgroundColor);if(this._focusedBackgroundColor!==newColor)this._focusedBackgroundColor=newColor,this.requestRender()}set focusedTextColor(value){let newColor=parseColor(value??this._defaultOptions.focusedTextColor);if(this._focusedTextColor!==newColor)this._focusedTextColor=newColor,this.requestRender()}set selectedBackgroundColor(value){let newColor=parseColor(value??this._defaultOptions.selectedBackgroundColor);if(this._selectedBackgroundColor!==newColor)this._selectedBackgroundColor=newColor,this.requestRender()}set selectedTextColor(value){let newColor=parseColor(value??this._defaultOptions.selectedTextColor);if(this._selectedTextColor!==newColor)this._selectedTextColor=newColor,this.requestRender()}set descriptionColor(value){let newColor=parseColor(value??this._defaultOptions.descriptionColor);if(this._descriptionColor!==newColor)this._descriptionColor=newColor,this.requestRender()}set selectedDescriptionColor(value){let newColor=parseColor(value??this._defaultOptions.selectedDescriptionColor);if(this._selectedDescriptionColor!==newColor)this._selectedDescriptionColor=newColor,this.requestRender()}set font(font){this._font=font,this.fontHeight=measureText({text:"A",font:this._font}).height,this.linesPerItem=this._showDescription?this._font?this.fontHeight+1:2:this._font?this.fontHeight:1,this.linesPerItem+=this._itemSpacing,this.maxVisibleItems=Math.max(1,Math.floor(this.height/this.linesPerItem)),this.updateScrollOffset(),this.requestRender()}set itemSpacing(spacing){this._itemSpacing=spacing,this.linesPerItem=this._showDescription?this._font?this.fontHeight+1:2:this._font?this.fontHeight:1,this.linesPerItem+=this._itemSpacing,this.maxVisibleItems=Math.max(1,Math.floor(this.height/this.linesPerItem)),this.updateScrollOffset(),this.requestRender()}set fastScrollStep(step){this._fastScrollStep=step}set keyBindings(bindings){this._keyBindings=bindings;let mergedBindings=mergeKeyBindings(defaultSelectKeybindings,bindings);this._keyBindingsMap=buildKeyBindingsMap(mergedBindings,this._keyAliasMap)}set keyAliasMap(aliases){this._keyAliasMap=mergeKeyAliases(defaultKeyAliases,aliases);let mergedBindings=mergeKeyBindings(defaultSelectKeybindings,this._keyBindings);this._keyBindingsMap=buildKeyBindingsMap(mergedBindings,this._keyAliasMap)}set selectedIndex(value){let newIndex=value??this._defaultOptions.selectedIndex,clampedIndex=this._options.length>0?Math.min(Math.max(0,newIndex),this._options.length-1):0;if(this._selectedIndex!==clampedIndex)this._selectedIndex=clampedIndex,this.updateScrollOffset(),this.requestRender()}}var defaultTabSelectKeybindings=[{name:"left",action:"move-left"},{name:"[",action:"move-left"},{name:"right",action:"move-right"},{name:"]",action:"move-right"},{name:"return",action:"select-current"},{name:"linefeed",action:"select-current"}],TabSelectRenderableEvents;((TabSelectRenderableEvents2)=>{TabSelectRenderableEvents2.SELECTION_CHANGED="selectionChanged",TabSelectRenderableEvents2.ITEM_SELECTED="itemSelected"})(TabSelectRenderableEvents||={});function calculateDynamicHeight(showUnderline,showDescription){let height=1;if(showUnderline)height+=1;if(showDescription)height+=1;return height}class TabSelectRenderable extends Renderable{_focusable=!0;_options=[];selectedIndex=0;scrollOffset=0;_tabWidth;maxVisibleTabs;_backgroundColor;_textColor;_focusedBackgroundColor;_focusedTextColor;_selectedBackgroundColor;_selectedTextColor;_selectedDescriptionColor;_showScrollArrows;_showDescription;_showUnderline;_wrapSelection;_keyBindingsMap;_keyAliasMap;_keyBindings;constructor(ctx,options){let calculatedHeight=calculateDynamicHeight(options.showUnderline??!0,options.showDescription??!0);super(ctx,{...options,height:calculatedHeight,buffered:!0});this._backgroundColor=parseColor(options.backgroundColor||"transparent"),this._textColor=parseColor(options.textColor||"#FFFFFF"),this._focusedBackgroundColor=parseColor(options.focusedBackgroundColor||options.backgroundColor||"#1a1a1a"),this._focusedTextColor=parseColor(options.focusedTextColor||options.textColor||"#FFFFFF"),this._options=options.options||[],this._tabWidth=options.tabWidth||20,this._showDescription=options.showDescription??!0,this._showUnderline=options.showUnderline??!0,this._showScrollArrows=options.showScrollArrows??!0,this._wrapSelection=options.wrapSelection??!1,this.maxVisibleTabs=Math.max(1,Math.floor(this.width/this._tabWidth)),this._selectedBackgroundColor=parseColor(options.selectedBackgroundColor||"#334455"),this._selectedTextColor=parseColor(options.selectedTextColor||"#FFFF00"),this._selectedDescriptionColor=parseColor(options.selectedDescriptionColor||"#CCCCCC"),this._keyAliasMap=mergeKeyAliases(defaultKeyAliases,options.keyAliasMap||{}),this._keyBindings=options.keyBindings||[];let mergedBindings=mergeKeyBindings(defaultTabSelectKeybindings,this._keyBindings);this._keyBindingsMap=buildKeyBindingsMap(mergedBindings,this._keyAliasMap)}calculateDynamicHeight(){return calculateDynamicHeight(this._showUnderline,this._showDescription)}renderSelf(buffer,deltaTime){if(!this.visible||!this.frameBuffer)return;if(this.isDirty)this.refreshFrameBuffer()}refreshFrameBuffer(){if(!this.frameBuffer)return;let bgColor=this._focused?this._focusedBackgroundColor:this._backgroundColor;if(this.frameBuffer.clear(bgColor),this._options.length===0)return;let contentX=0,contentY=0,contentWidth=this.width,contentHeight=this.height,visibleOptions=this._options.slice(this.scrollOffset,this.scrollOffset+this.maxVisibleTabs);for(let i=0;i<visibleOptions.length;i++){let actualIndex=this.scrollOffset+i,option=visibleOptions[i],isSelected=actualIndex===this.selectedIndex,tabX=contentX+i*this._tabWidth;if(tabX>=contentX+contentWidth)break;let actualTabWidth=Math.min(this._tabWidth,contentWidth-i*this._tabWidth);if(isSelected)this.frameBuffer.fillRect(tabX,contentY,actualTabWidth,1,this._selectedBackgroundColor);let baseTextColor=this._focused?this._focusedTextColor:this._textColor,nameColor=isSelected?this._selectedTextColor:baseTextColor,nameContent=this.truncateText(option.name,actualTabWidth-2);if(this.frameBuffer.drawText(nameContent,tabX+1,contentY,nameColor),isSelected&&this._showUnderline&&contentHeight>=2){let underlineY=contentY+1,underlineBg=isSelected?this._selectedBackgroundColor:bgColor;this.frameBuffer.drawText("\u25AC".repeat(actualTabWidth),tabX,underlineY,nameColor,underlineBg)}}if(this._showDescription&&contentHeight>=(this._showUnderline?3:2)){let selectedOption=this.getSelectedOption();if(selectedOption){let descriptionY=contentY+(this._showUnderline?2:1),descColor=this._selectedDescriptionColor,descContent=this.truncateText(selectedOption.description,contentWidth-2);this.frameBuffer.drawText(descContent,contentX+1,descriptionY,descColor)}}if(this._showScrollArrows&&this._options.length>this.maxVisibleTabs)this.renderScrollArrowsToFrameBuffer(contentX,contentY,contentWidth,contentHeight)}truncateText(text,maxWidth){if(text.length<=maxWidth)return text;return text.substring(0,Math.max(0,maxWidth-1))+"\u2026"}renderScrollArrowsToFrameBuffer(contentX,contentY,contentWidth,contentHeight){if(!this.frameBuffer)return;let hasMoreLeft=this.scrollOffset>0,hasMoreRight=this.scrollOffset+this.maxVisibleTabs<this._options.length;if(hasMoreLeft)this.frameBuffer.drawText("\u2039",contentX,contentY,parseColor("#AAAAAA"));if(hasMoreRight)this.frameBuffer.drawText("\u203A",contentX+contentWidth-1,contentY,parseColor("#AAAAAA"))}setOptions(options){this._options=options,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,options.length-1)),this.updateScrollOffset(),this.requestRender()}getSelectedOption(){return this._options[this.selectedIndex]||null}getSelectedIndex(){return this.selectedIndex}moveLeft(){if(this.selectedIndex>0)this.selectedIndex--;else if(this._wrapSelection&&this._options.length>0)this.selectedIndex=this._options.length-1;else return;this.updateScrollOffset(),this.requestRender(),this.emit("selectionChanged",this.selectedIndex,this.getSelectedOption())}moveRight(){if(this.selectedIndex<this._options.length-1)this.selectedIndex++;else if(this._wrapSelection&&this._options.length>0)this.selectedIndex=0;else return;this.updateScrollOffset(),this.requestRender(),this.emit("selectionChanged",this.selectedIndex,this.getSelectedOption())}selectCurrent(){let selected=this.getSelectedOption();if(selected)this.emit("itemSelected",this.selectedIndex,selected)}setSelectedIndex(index){if(index>=0&&index<this._options.length)this.selectedIndex=index,this.updateScrollOffset(),this.requestRender(),this.emit("selectionChanged",this.selectedIndex,this.getSelectedOption())}updateScrollOffset(){let halfVisible=Math.floor(this.maxVisibleTabs/2),newScrollOffset=Math.max(0,Math.min(this.selectedIndex-halfVisible,this._options.length-this.maxVisibleTabs));if(newScrollOffset!==this.scrollOffset)this.scrollOffset=newScrollOffset,this.requestRender()}onResize(width,height){this.maxVisibleTabs=Math.max(1,Math.floor(width/this._tabWidth)),this.updateScrollOffset(),this.requestRender()}setTabWidth(tabWidth){if(this._tabWidth===tabWidth)return;this._tabWidth=tabWidth,this.maxVisibleTabs=Math.max(1,Math.floor(this.width/this._tabWidth)),this.updateScrollOffset(),this.requestRender()}getTabWidth(){return this._tabWidth}handleKeyPress(key){let action=getKeyBindingAction(this._keyBindingsMap,key);if(action)switch(action){case"move-left":return this.moveLeft(),!0;case"move-right":return this.moveRight(),!0;case"select-current":return this.selectCurrent(),!0}return!1}get options(){return this._options}set options(options){this._options=options,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,options.length-1)),this.updateScrollOffset(),this.requestRender()}set backgroundColor(color){this._backgroundColor=parseColor(color),this.requestRender()}set textColor(color){this._textColor=parseColor(color),this.requestRender()}set focusedBackgroundColor(color){this._focusedBackgroundColor=parseColor(color),this.requestRender()}set focusedTextColor(color){this._focusedTextColor=parseColor(color),this.requestRender()}set selectedBackgroundColor(color){this._selectedBackgroundColor=parseColor(color),this.requestRender()}set selectedTextColor(color){this._selectedTextColor=parseColor(color),this.requestRender()}set selectedDescriptionColor(color){this._selectedDescriptionColor=parseColor(color),this.requestRender()}get showDescription(){return this._showDescription}set showDescription(show){if(this._showDescription!==show){this._showDescription=show;let newHeight=this.calculateDynamicHeight();this.height=newHeight,this.requestRender()}}get showUnderline(){return this._showUnderline}set showUnderline(show){if(this._showUnderline!==show){this._showUnderline=show;let newHeight=this.calculateDynamicHeight();this.height=newHeight,this.requestRender()}}get showScrollArrows(){return this._showScrollArrows}set showScrollArrows(show){if(this._showScrollArrows!==show)this._showScrollArrows=show,this.requestRender()}get wrapSelection(){return this._wrapSelection}set wrapSelection(wrap){this._wrapSelection=wrap}get tabWidth(){return this._tabWidth}set tabWidth(tabWidth){if(this._tabWidth===tabWidth)return;this._tabWidth=tabWidth,this.maxVisibleTabs=Math.max(1,Math.floor(this.width/this._tabWidth)),this.updateScrollOffset(),this.requestRender()}set keyBindings(bindings){this._keyBindings=bindings;let mergedBindings=mergeKeyBindings(defaultTabSelectKeybindings,bindings);this._keyBindingsMap=buildKeyBindingsMap(mergedBindings,this._keyAliasMap)}set keyAliasMap(aliases){this._keyAliasMap=mergeKeyAliases(defaultKeyAliases,aliases);let mergedBindings=mergeKeyBindings(defaultTabSelectKeybindings,this._keyBindings);this._keyBindingsMap=buildKeyBindingsMap(mergedBindings,this._keyAliasMap)}}class TimeToFirstDrawRenderable extends Renderable{_runtimeMs=null;textColor;label;precision;constructor(ctx,options={}){super(ctx,{width:"100%",height:1,flexShrink:0,alignSelf:"center",...options});this.textColor=parseColor(options.fg??"#AAAAAA"),this.label=options.label??"Time to first draw",this.precision=this.normalizePrecision(options.precision??2)}get runtimeMs(){return this._runtimeMs}set fg(value){this.textColor=parseColor(value),this.requestRender()}set color(value){this.fg=value}set textLabel(value){if(value===this.label)return;this.label=value,this.requestRender()}set decimals(value){let nextPrecision=this.normalizePrecision(value);if(nextPrecision===this.precision)return;this.precision=nextPrecision,this.requestRender()}reset(){this._runtimeMs=null,this.requestRender()}renderSelf(buffer){if(this._runtimeMs===null)this._runtimeMs=performance.now();let content=`${this.label}: ${this._runtimeMs.toFixed(this.precision)}ms`,maxWidth=Math.max(this.width,1),visibleContent=content.length>maxWidth?content.slice(0,maxWidth):content,centeredX=this.x+Math.max(0,Math.floor((maxWidth-visibleContent.length)/2));buffer.drawText(visibleContent,centeredX,this.y,this.textColor)}normalizePrecision(value){if(!Number.isFinite(value))return 2;return Math.max(0,Math.floor(value))}}var import_react=__toESM(require_react_production(),1);var import_react2=__toESM(require_react_production(),1),import_react3=__toESM(require_react_production(),1);var REACT_ELEMENT_TYPE=Symbol.for("react.transitional.element"),REACT_FRAGMENT_TYPE=Symbol.for("react.fragment");function jsxProd(type,config,maybeKey){var key=null;if(maybeKey!==void 0&&(key=""+maybeKey),config.key!==void 0&&(key=""+config.key),"key"in config){maybeKey={};for(var propName in config)propName!=="key"&&(maybeKey[propName]=config[propName])}else maybeKey=config;return config=maybeKey.ref,{$$typeof:REACT_ELEMENT_TYPE,type,key,ref:config!==void 0?config:null,props:maybeKey}}var $Fragment=REACT_FRAGMENT_TYPE,$jsx=jsxProd,$jsxs=jsxProd;var jsxDEV=$jsx;var import_react_reconciler=__toESM(require_react_reconciler_production(),1);var $ConcurrentRoot=1;var $DefaultEventPriority=32;var $NoEventPriority=0;var import_react4=__toESM(require_react_production(),1);var textNodeKeys=["span","b","strong","i","em","u","br","a"];class SpanRenderable extends TextNodeRenderable{ctx;constructor(ctx,options){super(options);this.ctx=ctx}}class TextModifierRenderable extends SpanRenderable{constructor(options,modifier){super(null,options);if(modifier==="b"||modifier==="strong")this.attributes=(this.attributes||0)|TextAttributes.BOLD;else if(modifier==="i"||modifier==="em")this.attributes=(this.attributes||0)|TextAttributes.ITALIC;else if(modifier==="u")this.attributes=(this.attributes||0)|TextAttributes.UNDERLINE}}class BoldSpanRenderable extends TextModifierRenderable{constructor(_ctx,options){super(options,"b")}}class ItalicSpanRenderable extends TextModifierRenderable{constructor(_ctx,options){super(options,"i")}}class UnderlineSpanRenderable extends TextModifierRenderable{constructor(_ctx,options){super(options,"u")}}class LineBreakRenderable extends SpanRenderable{constructor(_ctx,options){super(null,options);this.add()}add(){return super.add(`
|
|
3645
|
-
`)}}class LinkRenderable extends SpanRenderable{constructor(_ctx,options){let linkOptions={...options,link:{url:options.href}};super(null,linkOptions)}}var baseComponents={box:BoxRenderable,text:TextRenderable,code:CodeRenderable,diff:DiffRenderable,markdown:MarkdownRenderable,input:InputRenderable,select:SelectRenderable,textarea:TextareaRenderable,scrollbox:ScrollBoxRenderable,"ascii-font":ASCIIFontRenderable,"tab-select":TabSelectRenderable,"line-number":LineNumberRenderable,span:SpanRenderable,br:LineBreakRenderable,b:BoldSpanRenderable,strong:BoldSpanRenderable,i:ItalicSpanRenderable,em:ItalicSpanRenderable,u:UnderlineSpanRenderable,a:LinkRenderable},componentCatalogue={...baseComponents};function extend(objects){Object.assign(componentCatalogue,objects)}function getComponentCatalogue(){return componentCatalogue}var AppContext=import_react.createContext({keyHandler:null,renderer:null}),useAppContext=()=>{return import_react.useContext(AppContext)};class ErrorBoundary extends import_react3.default.Component{constructor(props){super(props);this.state={hasError:!1,error:null}}static getDerivedStateFromError(error){return{hasError:!0,error}}render(){if(this.state.hasError&&this.state.error)return jsxDEV("box",{style:{flexDirection:"column",padding:2},children:jsxDEV("text",{fg:"red",children:this.state.error.stack||this.state.error.message},void 0,!1,void 0,this)},void 0,!1,void 0,this);return this.props.children}}var package_default={name:"@opentui/react",version:"0.4.3",description:"React renderer for building terminal user interfaces using OpenTUI core",license:"MIT",repository:{type:"git",url:"https://github.com/anomalyco/opentui",directory:"packages/react"},module:"src/index.ts",type:"module",private:!0,main:"src/index.ts",exports:{".":{import:"./src/index.ts",types:"./src/index.ts"},"./test-utils":{import:"./src/test-utils.ts",types:"./src/test-utils.d.ts"},"./runtime-plugin-support":{import:"./scripts/runtime-plugin-support.ts",types:"./scripts/runtime-plugin-support.ts"},"./runtime-plugin-support/configure":{import:"./scripts/runtime-plugin-support-configure.ts",types:"./scripts/runtime-plugin-support-configure.ts"},"./jsx-runtime":{import:"./jsx-runtime.js",types:"./jsx-runtime.d.ts"},"./jsx-dev-runtime":{import:"./jsx-dev-runtime.js",types:"./jsx-dev-runtime.d.ts"}},scripts:{build:"bun run scripts/build.ts","build:examples":"bun examples/build.ts","build:dev":"bun run scripts/build.ts --dev",publish:"bun run scripts/publish.ts",test:"bun test"},devDependencies:{"@opentui/keymap":"workspace:*","@types/bun":"latest","@types/node":"^24.0.0","@types/react":"^19.2.0","@types/react-reconciler":"^0.33.0","@types/ws":"^8.18.1",react:">=19.2.0","react-devtools-core":"^7.0.1",typescript:"^5",ws:"^8.18.0"},peerDependencies:{react:">=19.2.0","react-devtools-core":"^7.0.1",ws:"^8.18.0"},peerDependenciesMeta:{"react-devtools-core":{optional:!0},ws:{optional:!0}},dependencies:{"@opentui/core":"workspace:*","react-reconciler":"^0.33.0"}},idCounter=new Map;function getNextId(type){if(!idCounter.has(type))idCounter.set(type,0);let value=idCounter.get(type)+1;return idCounter.set(type,value),`${type}-${value}`}function initEventListeners(instance,eventName,listener,previousListener){if(previousListener)instance.off(eventName,previousListener);if(listener)instance.on(eventName,listener)}function setStyle(instance,styles,oldStyles){if(oldStyles!=null&&typeof oldStyles==="object"){for(let styleName in oldStyles)if(oldStyles.hasOwnProperty(styleName)){if(styles==null||!styles.hasOwnProperty(styleName))instance[styleName]=null}}if(styles!=null&&typeof styles==="object"){for(let styleName in styles)if(styles.hasOwnProperty(styleName)){let value=styles[styleName],oldValue=oldStyles?.[styleName];if(value!==oldValue)instance[styleName]=value}}}function setProperty(instance,type,propKey,propValue,oldPropValue){switch(propKey){case"onChange":if(instance instanceof InputRenderable)initEventListeners(instance,InputRenderableEvents.CHANGE,propValue,oldPropValue);else if(instance instanceof SelectRenderable)initEventListeners(instance,SelectRenderableEvents.SELECTION_CHANGED,propValue,oldPropValue);else if(instance instanceof TabSelectRenderable)initEventListeners(instance,TabSelectRenderableEvents.SELECTION_CHANGED,propValue,oldPropValue);break;case"onInput":if(instance instanceof InputRenderable)initEventListeners(instance,InputRenderableEvents.INPUT,propValue,oldPropValue);break;case"onSubmit":if(instance instanceof InputRenderable)initEventListeners(instance,InputRenderableEvents.ENTER,propValue,oldPropValue);else if(instance instanceof TextareaRenderable)instance.onSubmit=propValue;break;case"onSelect":if(instance instanceof SelectRenderable)initEventListeners(instance,SelectRenderableEvents.ITEM_SELECTED,propValue,oldPropValue);else if(instance instanceof TabSelectRenderable)initEventListeners(instance,TabSelectRenderableEvents.ITEM_SELECTED,propValue,oldPropValue);break;case"focused":if(isRenderable(instance))if(propValue)instance.focus();else instance.blur();break;case"style":setStyle(instance,propValue,oldPropValue);break;case"children":break;default:instance[propKey]=propValue}}function setInitialProperties(instance,type,props){for(let propKey in props){if(!props.hasOwnProperty(propKey))continue;let propValue=props[propKey];if(propValue==null)continue;setProperty(instance,type,propKey,propValue)}}function updateProperties(instance,type,oldProps,newProps){for(let propKey in oldProps){let oldProp=oldProps[propKey];if(oldProps.hasOwnProperty(propKey)&&oldProp!=null&&!newProps.hasOwnProperty(propKey))setProperty(instance,type,propKey,null,oldProp)}for(let propKey in newProps){let newProp=newProps[propKey],oldProp=oldProps[propKey];if(newProps.hasOwnProperty(propKey)&&newProp!==oldProp&&(newProp!=null||oldProp!=null))setProperty(instance,type,propKey,newProp,oldProp)}}var currentUpdatePriority=$NoEventPriority,hostConfig={supportsMutation:!0,supportsPersistence:!1,supportsHydration:!1,supportsMicrotasks:!0,scheduleMicrotask:queueMicrotask,createInstance(type,props,rootContainerInstance,hostContext){if(textNodeKeys.includes(type)&&!hostContext.isInsideText)throw Error(`Component of type "${type}" must be created inside of a text node`);let id=getNextId(type),components=getComponentCatalogue();if(!components[type])throw Error(`Unknown component type: ${type}`);return new components[type](rootContainerInstance.ctx,{id,...props})},appendChild(parent,child){parent.add(child)},removeChild(parent,child){if(!child.parent)return;parent.remove(child)},insertBefore(parent,child,beforeChild){parent.insertBefore(child,beforeChild)},insertInContainerBefore(parent,child,beforeChild){parent.insertBefore(child,beforeChild)},removeChildFromContainer(parent,child){if(!child.parent)return;parent.remove(child)},prepareForCommit(containerInfo){return null},resetAfterCommit(containerInfo){containerInfo.requestRender()},getRootHostContext(rootContainerInstance){return{isInsideText:!1}},getChildHostContext(parentHostContext,type,rootContainerInstance){let isInsideText=["text",...textNodeKeys].includes(type);return{...parentHostContext,isInsideText}},shouldSetTextContent(type,props){return!1},createTextInstance(text,rootContainerInstance,hostContext){if(!hostContext.isInsideText)throw Error("Text must be created inside of a text node");return TextNodeRenderable.fromString(text)},scheduleTimeout:setTimeout,cancelTimeout:clearTimeout,noTimeout:-1,shouldAttemptEagerTransition(){return!0},finalizeInitialChildren(instance,type,props,rootContainerInstance,hostContext){return setInitialProperties(instance,type,props),!1},commitMount(instance,type,props,internalInstanceHandle){},commitUpdate(instance,type,oldProps,newProps,internalInstanceHandle){updateProperties(instance,type,oldProps,newProps)},commitTextUpdate(textInstance,oldText,newText){textInstance.children=[newText]},appendChildToContainer(container,child){container.add(child)},appendInitialChild(parent,child){parent.add(child)},hideInstance(instance){instance.visible=!1},unhideInstance(instance,props){instance.visible=!0},hideTextInstance(textInstance){textInstance.visible=!1},unhideTextInstance(textInstance,text){textInstance.visible=!0},clearContainer(container){container.getChildren().forEach((child)=>container.remove(child))},setCurrentUpdatePriority(newPriority){currentUpdatePriority=newPriority},getCurrentUpdatePriority:()=>currentUpdatePriority,resolveUpdatePriority(){if(currentUpdatePriority!==$NoEventPriority)return currentUpdatePriority;return $DefaultEventPriority},maySuspendCommit(){return!1},maySuspendCommitOnUpdate(){return!1},maySuspendCommitInSyncRender(){return!1},NotPendingTransition:null,HostTransitionContext:import_react4.createContext(null),resetFormInstance(){},requestPostPaintCallback(){},trackSchedulerEvent(){},resolveEventType(){return null},resolveEventTimeStamp(){return-1.1},preloadInstance(){return!0},startSuspendingCommit(){},suspendInstance(){},waitForCommitToBeReady(){return null},detachDeletedInstance(instance){if(!instance.parent)instance.destroyRecursively()},getPublicInstance(instance){return instance},preparePortalMount(containerInfo){},isPrimaryRenderer:!0,getInstanceFromNode(){return null},beforeActiveInstanceBlur(){},afterActiveInstanceBlur(){},prepareScopeUpdate(){},getInstanceFromScope(){return null},rendererPackageName:"@opentui/react",rendererVersion:package_default.version},reconciler=import_react_reconciler.default(hostConfig);reconciler.injectIntoDevTools();function _render(element,root){let container=reconciler.createContainer(root,$ConcurrentRoot,null,!1,null,"",console.error,console.error,console.error,()=>{});return reconciler.updateContainer(element,container,null,()=>{}),container}var _r=reconciler,flushSync=_r.flushSyncFromReconciler??_r.flushSync;function createRoot(renderer){let container=null,cleanup=()=>{if(container)reconciler.updateContainer(null,container,null,()=>{}),reconciler.flushSyncWork(),container=null};return renderer.once(CliRenderEvents.DESTROY,cleanup),{render:(node)=>{engine.attach(renderer),container=_render(import_react2.default.createElement(AppContext.Provider,{value:{keyHandler:renderer.keyInput,renderer}},import_react2.default.createElement(ErrorBoundary,null,node)),renderer.root)},unmount:cleanup}}var import_react5=__toESM(require_react_production(),1),import_react6=__toESM(require_react_production(),1),import_react7=__toESM(require_react_production(),1),import_react8=__toESM(require_react_production(),1),import_react9=__toESM(require_react_production(),1),import_react10=__toESM(require_react_production(),1),import_react11=__toESM(require_react_production(),1),import_react12=__toESM(require_react_production(),1);var import_react13=__toESM(require_react_production(),1);var import_react14=__toESM(require_react_production(),1);var import_react15=__toESM(require_react_production(),1),import_react16=__toESM(require_react_production(),1);function useEffectEvent(handler){let handlerRef=import_react6.useRef(handler);return import_react6.useLayoutEffect(()=>{handlerRef.current=handler}),import_react6.useCallback((...args)=>{let fn=handlerRef.current;return fn(...args)},[])}var useRenderer=()=>{let{renderer}=useAppContext();if(!renderer)throw Error("Renderer not found.");return renderer};var useKeyboard=(handler,options={release:!1})=>{let{keyHandler}=useAppContext(),stableHandler=useEffectEvent(handler);import_react8.useEffect(()=>{if(keyHandler?.on("keypress",stableHandler),options?.release)keyHandler?.on("keyrelease",stableHandler);return()=>{if(keyHandler?.off("keypress",stableHandler),options?.release)keyHandler?.off("keyrelease",stableHandler)}},[keyHandler,options.release])};var useOnResize=(callback)=>{let renderer=useRenderer(),stableCallback=useEffectEvent(callback);return import_react10.useEffect(()=>{return renderer.on("resize",stableCallback),()=>{renderer.off("resize",stableCallback)}},[renderer]),renderer};var useTerminalDimensions=()=>{let renderer=useRenderer(),[dimensions,setDimensions]=import_react12.useState({width:renderer.width,height:renderer.height});return useOnResize((width,height)=>{setDimensions({width,height})}),dimensions};function createReactSlotRegistry(renderer,context,options={}){return createSlotRegistry(renderer,"react:slot-registry",context,options)}function renderPluginFailurePlaceholder(registry,pluginFailurePlaceholder,failure,pluginId,slot){if(!pluginFailurePlaceholder)return null;try{return pluginFailurePlaceholder(failure)}catch(error){return registry.reportPluginError({pluginId,slot,phase:"error_placeholder",source:"react",error}),null}}class PluginErrorBoundary extends import_react14.default.Component{constructor(props){super(props);this.state={failure:null}}componentDidCatch(error){let failure=this.props.registry.reportPluginError({pluginId:this.props.pluginId,slot:this.props.slotName,phase:"render",source:"react",error});this.setState({failure})}componentDidUpdate(previousProps){if(previousProps.resetToken!==this.props.resetToken&&this.state.failure)this.setState({failure:null})}render(){if(this.state.failure){let placeholder=renderPluginFailurePlaceholder(this.props.registry,this.props.pluginFailurePlaceholder,this.state.failure,this.props.pluginId,this.props.slotName);if(placeholder===null||placeholder===void 0||placeholder===!1)return this.props.fallbackOnFailure??null;return placeholder}return this.props.children}}function getSlotProps(props){let{children:_children,mode:_mode,name:_name,registry:_registry,pluginFailurePlaceholder:_pluginFailurePlaceholder,...slotProps}=props;return slotProps}function createSlot(registry,options={}){return function(props){return jsxDEV(Slot,{...props,registry,pluginFailurePlaceholder:options.pluginFailurePlaceholder},void 0,!1,void 0,this)}}function Slot(props){let[version,setVersion]=import_react14.useState(0),registry=props.registry,slotName=String(props.name),renderFailuresByPluginRef=import_react14.useRef(new Map),pendingRenderReportsRef=import_react14.useRef(new Map);import_react14.useEffect(()=>{return registry.subscribe(()=>{setVersion((current)=>current+1)})},[registry]),import_react14.useEffect(()=>{if(pendingRenderReportsRef.current.size===0)return;let pendingReports=[...pendingRenderReportsRef.current.values()];pendingRenderReportsRef.current.clear();for(let report of pendingReports){let failure=registry.reportPluginError({pluginId:report.pluginId,slot:report.slot,phase:"render",source:"react",error:report.error});renderFailuresByPluginRef.current.set(`${report.slot}:${report.pluginId}:render`,failure)}});let entries=import_react14.useMemo(()=>registry.resolveEntries(props.name),[registry,props.name,version]),slotProps=getSlotProps(props),renderEntry=(entry,fallbackOnFailure)=>{let key=`${slotName}:${entry.id}`,failureKey=`${slotName}:${entry.id}:render`;try{let rendered=entry.renderer(registry.context,slotProps);return renderFailuresByPluginRef.current.delete(failureKey),pendingRenderReportsRef.current.delete(failureKey),jsxDEV(PluginErrorBoundary,{registry,pluginFailurePlaceholder:props.pluginFailurePlaceholder,pluginId:entry.id,slotName,resetToken:version,fallbackOnFailure,children:rendered},key,!1,void 0,this)}catch(error){let normalizedError=error instanceof Error?error:typeof error==="string"?Error(error):Error(String(error)),lastFailure=renderFailuresByPluginRef.current.get(failureKey),isSameFailure=lastFailure&&lastFailure.error.message===normalizedError.message;if(!isSameFailure){let queued=pendingRenderReportsRef.current.get(failureKey);if(!queued||queued.error.message!==normalizedError.message)pendingRenderReportsRef.current.set(failureKey,{pluginId:entry.id,slot:slotName,error:normalizedError})}let failure=isSameFailure&&lastFailure?lastFailure:{pluginId:entry.id,slot:slotName,phase:"render",source:"react",error:normalizedError,timestamp:Date.now()};renderFailuresByPluginRef.current.set(failureKey,failure);let placeholder=renderPluginFailurePlaceholder(registry,props.pluginFailurePlaceholder,failure,entry.id,slotName);if(placeholder===null||placeholder===void 0||placeholder===!1)return fallbackOnFailure??null;return jsxDEV(import_react14.Fragment,{children:placeholder},key,!1,void 0,this)}};if(entries.length===0)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);if(props.mode==="single_winner"){let winner=entries[0];if(!winner)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);let rendered=renderEntry(winner,props.children);if(rendered===null||rendered===void 0||rendered===!1)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);return jsxDEV($Fragment,{children:rendered},void 0,!1,void 0,this)}if(props.mode==="replace"){if(entries.length===1){let rendered=renderEntry(entries[0],props.children);if(rendered===null||rendered===void 0||rendered===!1)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);return jsxDEV($Fragment,{children:rendered},void 0,!1,void 0,this)}let renderedEntries=entries.map((entry)=>renderEntry(entry));if(!renderedEntries.some((node)=>node!==null&&node!==void 0&&node!==!1))return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);return jsxDEV($Fragment,{children:renderedEntries},void 0,!1,void 0,this)}return jsxDEV($Fragment,{children:[props.children,entries.map((entry)=>renderEntry(entry))]},void 0,!0,void 0,this)}extend({"time-to-first-draw":TimeToFirstDrawRenderable});init_perf();var import_react163=__toESM(require_react_production(),1);var INTERP_RE=/\{!(.+?)\}/g,hasInterp=(s)=>/\{!.+?\}/.test(s);async function interpolate(gw,text){let hits=[...text.matchAll(INTERP_RE)];if(hits.length===0)return text;let outs=await Promise.all(hits.map((m2)=>gw.request("shell.exec",{command:m2[1]}).then((r)=>[r.stdout,r.stderr].filter(Boolean).join(`
|
|
3645
|
+
`)}}class LinkRenderable extends SpanRenderable{constructor(_ctx,options){let linkOptions={...options,link:{url:options.href}};super(null,linkOptions)}}var baseComponents={box:BoxRenderable,text:TextRenderable,code:CodeRenderable,diff:DiffRenderable,markdown:MarkdownRenderable,input:InputRenderable,select:SelectRenderable,textarea:TextareaRenderable,scrollbox:ScrollBoxRenderable,"ascii-font":ASCIIFontRenderable,"tab-select":TabSelectRenderable,"line-number":LineNumberRenderable,span:SpanRenderable,br:LineBreakRenderable,b:BoldSpanRenderable,strong:BoldSpanRenderable,i:ItalicSpanRenderable,em:ItalicSpanRenderable,u:UnderlineSpanRenderable,a:LinkRenderable},componentCatalogue={...baseComponents};function extend(objects){Object.assign(componentCatalogue,objects)}function getComponentCatalogue(){return componentCatalogue}var AppContext=import_react.createContext({keyHandler:null,renderer:null}),useAppContext=()=>{return import_react.useContext(AppContext)};class ErrorBoundary extends import_react3.default.Component{constructor(props){super(props);this.state={hasError:!1,error:null}}static getDerivedStateFromError(error){return{hasError:!0,error}}render(){if(this.state.hasError&&this.state.error)return jsxDEV("box",{style:{flexDirection:"column",padding:2},children:jsxDEV("text",{fg:"red",children:this.state.error.stack||this.state.error.message},void 0,!1,void 0,this)},void 0,!1,void 0,this);return this.props.children}}var package_default={name:"@opentui/react",version:"0.4.3",description:"React renderer for building terminal user interfaces using OpenTUI core",license:"MIT",repository:{type:"git",url:"https://github.com/anomalyco/opentui",directory:"packages/react"},module:"src/index.ts",type:"module",private:!0,main:"src/index.ts",exports:{".":{import:"./src/index.ts",types:"./src/index.ts"},"./test-utils":{import:"./src/test-utils.ts",types:"./src/test-utils.d.ts"},"./runtime-plugin-support":{import:"./scripts/runtime-plugin-support.ts",types:"./scripts/runtime-plugin-support.ts"},"./runtime-plugin-support/configure":{import:"./scripts/runtime-plugin-support-configure.ts",types:"./scripts/runtime-plugin-support-configure.ts"},"./jsx-runtime":{import:"./jsx-runtime.js",types:"./jsx-runtime.d.ts"},"./jsx-dev-runtime":{import:"./jsx-dev-runtime.js",types:"./jsx-dev-runtime.d.ts"}},scripts:{build:"bun run scripts/build.ts","build:examples":"bun examples/build.ts","build:dev":"bun run scripts/build.ts --dev",publish:"bun run scripts/publish.ts",test:"bun test"},devDependencies:{"@opentui/keymap":"workspace:*","@types/bun":"latest","@types/node":"^24.0.0","@types/react":"^19.2.0","@types/react-reconciler":"^0.33.0","@types/ws":"^8.18.1",react:">=19.2.0","react-devtools-core":"^7.0.1",typescript:"^5",ws:"^8.18.0"},peerDependencies:{react:">=19.2.0","react-devtools-core":"^7.0.1",ws:"^8.18.0"},peerDependenciesMeta:{"react-devtools-core":{optional:!0},ws:{optional:!0}},dependencies:{"@opentui/core":"workspace:*","react-reconciler":"^0.33.0"}},idCounter=new Map;function getNextId(type){if(!idCounter.has(type))idCounter.set(type,0);let value=idCounter.get(type)+1;return idCounter.set(type,value),`${type}-${value}`}function initEventListeners(instance,eventName,listener,previousListener){if(previousListener)instance.off(eventName,previousListener);if(listener)instance.on(eventName,listener)}function setStyle(instance,styles,oldStyles){if(oldStyles!=null&&typeof oldStyles==="object"){for(let styleName in oldStyles)if(oldStyles.hasOwnProperty(styleName)){if(styles==null||!styles.hasOwnProperty(styleName))instance[styleName]=null}}if(styles!=null&&typeof styles==="object"){for(let styleName in styles)if(styles.hasOwnProperty(styleName)){let value=styles[styleName],oldValue=oldStyles?.[styleName];if(value!==oldValue)instance[styleName]=value}}}function setProperty(instance,type,propKey,propValue,oldPropValue){switch(propKey){case"onChange":if(instance instanceof InputRenderable)initEventListeners(instance,InputRenderableEvents.CHANGE,propValue,oldPropValue);else if(instance instanceof SelectRenderable)initEventListeners(instance,SelectRenderableEvents.SELECTION_CHANGED,propValue,oldPropValue);else if(instance instanceof TabSelectRenderable)initEventListeners(instance,TabSelectRenderableEvents.SELECTION_CHANGED,propValue,oldPropValue);break;case"onInput":if(instance instanceof InputRenderable)initEventListeners(instance,InputRenderableEvents.INPUT,propValue,oldPropValue);break;case"onSubmit":if(instance instanceof InputRenderable)initEventListeners(instance,InputRenderableEvents.ENTER,propValue,oldPropValue);else if(instance instanceof TextareaRenderable)instance.onSubmit=propValue;break;case"onSelect":if(instance instanceof SelectRenderable)initEventListeners(instance,SelectRenderableEvents.ITEM_SELECTED,propValue,oldPropValue);else if(instance instanceof TabSelectRenderable)initEventListeners(instance,TabSelectRenderableEvents.ITEM_SELECTED,propValue,oldPropValue);break;case"focused":if(isRenderable(instance))if(propValue)instance.focus();else instance.blur();break;case"style":setStyle(instance,propValue,oldPropValue);break;case"children":break;default:instance[propKey]=propValue}}function setInitialProperties(instance,type,props){for(let propKey in props){if(!props.hasOwnProperty(propKey))continue;let propValue=props[propKey];if(propValue==null)continue;setProperty(instance,type,propKey,propValue)}}function updateProperties(instance,type,oldProps,newProps){for(let propKey in oldProps){let oldProp=oldProps[propKey];if(oldProps.hasOwnProperty(propKey)&&oldProp!=null&&!newProps.hasOwnProperty(propKey))setProperty(instance,type,propKey,null,oldProp)}for(let propKey in newProps){let newProp=newProps[propKey],oldProp=oldProps[propKey];if(newProps.hasOwnProperty(propKey)&&newProp!==oldProp&&(newProp!=null||oldProp!=null))setProperty(instance,type,propKey,newProp,oldProp)}}var currentUpdatePriority=$NoEventPriority,hostConfig={supportsMutation:!0,supportsPersistence:!1,supportsHydration:!1,supportsMicrotasks:!0,scheduleMicrotask:queueMicrotask,createInstance(type,props,rootContainerInstance,hostContext){if(textNodeKeys.includes(type)&&!hostContext.isInsideText)throw Error(`Component of type "${type}" must be created inside of a text node`);let id=getNextId(type),components=getComponentCatalogue();if(!components[type])throw Error(`Unknown component type: ${type}`);return new components[type](rootContainerInstance.ctx,{id,...props})},appendChild(parent,child){parent.add(child)},removeChild(parent,child){if(!child.parent)return;parent.remove(child)},insertBefore(parent,child,beforeChild){parent.insertBefore(child,beforeChild)},insertInContainerBefore(parent,child,beforeChild){parent.insertBefore(child,beforeChild)},removeChildFromContainer(parent,child){if(!child.parent)return;parent.remove(child)},prepareForCommit(containerInfo){return null},resetAfterCommit(containerInfo){containerInfo.requestRender()},getRootHostContext(rootContainerInstance){return{isInsideText:!1}},getChildHostContext(parentHostContext,type,rootContainerInstance){let isInsideText=["text",...textNodeKeys].includes(type);return{...parentHostContext,isInsideText}},shouldSetTextContent(type,props){return!1},createTextInstance(text,rootContainerInstance,hostContext){if(!hostContext.isInsideText)throw Error("Text must be created inside of a text node");return TextNodeRenderable.fromString(text)},scheduleTimeout:setTimeout,cancelTimeout:clearTimeout,noTimeout:-1,shouldAttemptEagerTransition(){return!0},finalizeInitialChildren(instance,type,props,rootContainerInstance,hostContext){return setInitialProperties(instance,type,props),!1},commitMount(instance,type,props,internalInstanceHandle){},commitUpdate(instance,type,oldProps,newProps,internalInstanceHandle){updateProperties(instance,type,oldProps,newProps)},commitTextUpdate(textInstance,oldText,newText){textInstance.children=[newText]},appendChildToContainer(container,child){container.add(child)},appendInitialChild(parent,child){parent.add(child)},hideInstance(instance){instance.visible=!1},unhideInstance(instance,props){instance.visible=!0},hideTextInstance(textInstance){textInstance.visible=!1},unhideTextInstance(textInstance,text){textInstance.visible=!0},clearContainer(container){container.getChildren().forEach((child)=>container.remove(child))},setCurrentUpdatePriority(newPriority){currentUpdatePriority=newPriority},getCurrentUpdatePriority:()=>currentUpdatePriority,resolveUpdatePriority(){if(currentUpdatePriority!==$NoEventPriority)return currentUpdatePriority;return $DefaultEventPriority},maySuspendCommit(){return!1},maySuspendCommitOnUpdate(){return!1},maySuspendCommitInSyncRender(){return!1},NotPendingTransition:null,HostTransitionContext:import_react4.createContext(null),resetFormInstance(){},requestPostPaintCallback(){},trackSchedulerEvent(){},resolveEventType(){return null},resolveEventTimeStamp(){return-1.1},preloadInstance(){return!0},startSuspendingCommit(){},suspendInstance(){},waitForCommitToBeReady(){return null},detachDeletedInstance(instance){if(!instance.parent)instance.destroyRecursively()},getPublicInstance(instance){return instance},preparePortalMount(containerInfo){},isPrimaryRenderer:!0,getInstanceFromNode(){return null},beforeActiveInstanceBlur(){},afterActiveInstanceBlur(){},prepareScopeUpdate(){},getInstanceFromScope(){return null},rendererPackageName:"@opentui/react",rendererVersion:package_default.version},reconciler=import_react_reconciler.default(hostConfig);reconciler.injectIntoDevTools();function _render(element,root){let container=reconciler.createContainer(root,$ConcurrentRoot,null,!1,null,"",console.error,console.error,console.error,()=>{});return reconciler.updateContainer(element,container,null,()=>{}),container}var _r=reconciler,flushSync=_r.flushSyncFromReconciler??_r.flushSync;function createRoot(renderer){let container=null,cleanup=()=>{if(container)reconciler.updateContainer(null,container,null,()=>{}),reconciler.flushSyncWork(),container=null};return renderer.once(CliRenderEvents.DESTROY,cleanup),{render:(node)=>{engine.attach(renderer),container=_render(import_react2.default.createElement(AppContext.Provider,{value:{keyHandler:renderer.keyInput,renderer}},import_react2.default.createElement(ErrorBoundary,null,node)),renderer.root)},unmount:cleanup}}var import_react5=__toESM(require_react_production(),1),import_react6=__toESM(require_react_production(),1),import_react7=__toESM(require_react_production(),1),import_react8=__toESM(require_react_production(),1),import_react9=__toESM(require_react_production(),1),import_react10=__toESM(require_react_production(),1),import_react11=__toESM(require_react_production(),1),import_react12=__toESM(require_react_production(),1);var import_react13=__toESM(require_react_production(),1);var import_react14=__toESM(require_react_production(),1);var import_react15=__toESM(require_react_production(),1),import_react16=__toESM(require_react_production(),1);function useEffectEvent(handler){let handlerRef=import_react6.useRef(handler);return import_react6.useLayoutEffect(()=>{handlerRef.current=handler}),import_react6.useCallback((...args)=>{let fn=handlerRef.current;return fn(...args)},[])}var useRenderer=()=>{let{renderer}=useAppContext();if(!renderer)throw Error("Renderer not found.");return renderer};var useKeyboard=(handler,options={release:!1})=>{let{keyHandler}=useAppContext(),stableHandler=useEffectEvent(handler);import_react8.useEffect(()=>{if(keyHandler?.on("keypress",stableHandler),options?.release)keyHandler?.on("keyrelease",stableHandler);return()=>{if(keyHandler?.off("keypress",stableHandler),options?.release)keyHandler?.off("keyrelease",stableHandler)}},[keyHandler,options.release])};var useOnResize=(callback)=>{let renderer=useRenderer(),stableCallback=useEffectEvent(callback);return import_react10.useEffect(()=>{return renderer.on("resize",stableCallback),()=>{renderer.off("resize",stableCallback)}},[renderer]),renderer};var useTerminalDimensions=()=>{let renderer=useRenderer(),[dimensions,setDimensions]=import_react12.useState({width:renderer.width,height:renderer.height});return useOnResize((width,height)=>{setDimensions({width,height})}),dimensions};function createReactSlotRegistry(renderer,context,options={}){return createSlotRegistry(renderer,"react:slot-registry",context,options)}function renderPluginFailurePlaceholder(registry,pluginFailurePlaceholder,failure,pluginId,slot){if(!pluginFailurePlaceholder)return null;try{return pluginFailurePlaceholder(failure)}catch(error){return registry.reportPluginError({pluginId,slot,phase:"error_placeholder",source:"react",error}),null}}class PluginErrorBoundary extends import_react14.default.Component{constructor(props){super(props);this.state={failure:null}}componentDidCatch(error){let failure=this.props.registry.reportPluginError({pluginId:this.props.pluginId,slot:this.props.slotName,phase:"render",source:"react",error});this.setState({failure})}componentDidUpdate(previousProps){if(previousProps.resetToken!==this.props.resetToken&&this.state.failure)this.setState({failure:null})}render(){if(this.state.failure){let placeholder=renderPluginFailurePlaceholder(this.props.registry,this.props.pluginFailurePlaceholder,this.state.failure,this.props.pluginId,this.props.slotName);if(placeholder===null||placeholder===void 0||placeholder===!1)return this.props.fallbackOnFailure??null;return placeholder}return this.props.children}}function getSlotProps(props){let{children:_children,mode:_mode,name:_name,registry:_registry,pluginFailurePlaceholder:_pluginFailurePlaceholder,...slotProps}=props;return slotProps}function createSlot(registry,options={}){return function(props){return jsxDEV(Slot,{...props,registry,pluginFailurePlaceholder:options.pluginFailurePlaceholder},void 0,!1,void 0,this)}}function Slot(props){let[version,setVersion]=import_react14.useState(0),registry=props.registry,slotName=String(props.name),renderFailuresByPluginRef=import_react14.useRef(new Map),pendingRenderReportsRef=import_react14.useRef(new Map);import_react14.useEffect(()=>{return registry.subscribe(()=>{setVersion((current)=>current+1)})},[registry]),import_react14.useEffect(()=>{if(pendingRenderReportsRef.current.size===0)return;let pendingReports=[...pendingRenderReportsRef.current.values()];pendingRenderReportsRef.current.clear();for(let report of pendingReports){let failure=registry.reportPluginError({pluginId:report.pluginId,slot:report.slot,phase:"render",source:"react",error:report.error});renderFailuresByPluginRef.current.set(`${report.slot}:${report.pluginId}:render`,failure)}});let entries=import_react14.useMemo(()=>registry.resolveEntries(props.name),[registry,props.name,version]),slotProps=getSlotProps(props),renderEntry=(entry,fallbackOnFailure)=>{let key=`${slotName}:${entry.id}`,failureKey=`${slotName}:${entry.id}:render`;try{let rendered=entry.renderer(registry.context,slotProps);return renderFailuresByPluginRef.current.delete(failureKey),pendingRenderReportsRef.current.delete(failureKey),jsxDEV(PluginErrorBoundary,{registry,pluginFailurePlaceholder:props.pluginFailurePlaceholder,pluginId:entry.id,slotName,resetToken:version,fallbackOnFailure,children:rendered},key,!1,void 0,this)}catch(error){let normalizedError=error instanceof Error?error:typeof error==="string"?Error(error):Error(String(error)),lastFailure=renderFailuresByPluginRef.current.get(failureKey),isSameFailure=lastFailure&&lastFailure.error.message===normalizedError.message;if(!isSameFailure){let queued=pendingRenderReportsRef.current.get(failureKey);if(!queued||queued.error.message!==normalizedError.message)pendingRenderReportsRef.current.set(failureKey,{pluginId:entry.id,slot:slotName,error:normalizedError})}let failure=isSameFailure&&lastFailure?lastFailure:{pluginId:entry.id,slot:slotName,phase:"render",source:"react",error:normalizedError,timestamp:Date.now()};renderFailuresByPluginRef.current.set(failureKey,failure);let placeholder=renderPluginFailurePlaceholder(registry,props.pluginFailurePlaceholder,failure,entry.id,slotName);if(placeholder===null||placeholder===void 0||placeholder===!1)return fallbackOnFailure??null;return jsxDEV(import_react14.Fragment,{children:placeholder},key,!1,void 0,this)}};if(entries.length===0)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);if(props.mode==="single_winner"){let winner=entries[0];if(!winner)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);let rendered=renderEntry(winner,props.children);if(rendered===null||rendered===void 0||rendered===!1)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);return jsxDEV($Fragment,{children:rendered},void 0,!1,void 0,this)}if(props.mode==="replace"){if(entries.length===1){let rendered=renderEntry(entries[0],props.children);if(rendered===null||rendered===void 0||rendered===!1)return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);return jsxDEV($Fragment,{children:rendered},void 0,!1,void 0,this)}let renderedEntries=entries.map((entry)=>renderEntry(entry));if(!renderedEntries.some((node)=>node!==null&&node!==void 0&&node!==!1))return jsxDEV($Fragment,{children:props.children},void 0,!1,void 0,this);return jsxDEV($Fragment,{children:renderedEntries},void 0,!1,void 0,this)}return jsxDEV($Fragment,{children:[props.children,entries.map((entry)=>renderEntry(entry))]},void 0,!0,void 0,this)}extend({"time-to-first-draw":TimeToFirstDrawRenderable});init_perf();var import_react165=__toESM(require_react_production(),1);var INTERP_RE=/\{!(.+?)\}/g,hasInterp=(s)=>/\{!.+?\}/.test(s);async function interpolate(gw,text){let hits=[...text.matchAll(INTERP_RE)];if(hits.length===0)return text;let outs=await Promise.all(hits.map((m2)=>gw.request("shell.exec",{command:m2[1]}).then((r)=>[r.stdout,r.stderr].filter(Boolean).join(`
|
|
3646
3646
|
`).trim()).catch(()=>"(error)"))),out=text;for(let i=hits.length-1;i>=0;i--){let m2=hits[i];out=out.slice(0,m2.index)+outs[i]+out.slice(m2.index+m2[0].length)}return out}var import_react17=__toESM(require_react_production(),1);import{EventEmitter as EventEmitter7}from"events";import{homedir}from"os";import{resolve as resolve3,delimiter}from"path";import{existsSync as existsSync4}from"fs";var BAD=/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDFFF]/g;function scalar(s){let count2=0;return{text:s.replace(BAD,(m2)=>{if(m2.length===2)return m2;return count2+=1,"\uFFFD"}),count:count2}}function encode(v2){let paths=new WeakMap,issues=[];return{text:JSON.stringify(v2,function(key,value){let holder=this&&typeof this==="object"?paths.get(this):void 0,path4=key?`${holder??"$"}.${key}`:"$";if(value&&typeof value==="object")paths.set(value,path4);if(typeof value!=="string")return value;let next=scalar(value);if(next.count>0)issues.push({path:path4,count:next.count});return next.text})??"null",issues}}var LOG_MAX=200,LOG_PREVIEW=240,STARTUP_MS=15000,REQUEST_MS=120000,WS_CONNECTING=0,WS_OPEN=1,WS_CLOSING=2,WS_CLOSED=3,decoder2=new TextDecoder;function hermesAgentRoot(){if(process.env.HERMES_AGENT_ROOT)return process.env.HERMES_AGENT_ROOT;let homePath=`${process.env.HOME||homedir()}/.hermes/hermes-agent`;if(existsSync4(homePath))return homePath;let fhs="/usr/local/lib/hermes-agent";if(existsSync4(fhs))return fhs;return homePath}function gatewayUrl(){return process.env.HERM_GATEWAY_URL?.trim()||process.env.HERMES_TUI_GATEWAY_URL?.trim()||null}function websocketUrl(raw){let url=new URL(raw);if(url.protocol==="http:")url.protocol="ws:";else if(url.protocol==="https:")url.protocol="wss:";else if(url.protocol!=="ws:"&&url.protocol!=="wss:")throw Error(`unsupported gateway URL protocol: ${url.protocol}`);let prefix=url.pathname.replace(/\/+$/,"");if(!prefix.endsWith("/api/ws"))url.pathname=`${prefix}/api/ws`;return url.toString()}function redact(raw){try{let url=new URL(raw);if(url.username||url.password)url.username="***",url.password="";if(url.search)url.search="?***";return url.toString()}catch{return"invalid gateway URL"}}function python(root,platform=process.platform){let env2=process.env.HERMES_PYTHON?.trim();if(env2)return env2;let venv=process.env.VIRTUAL_ENV?.trim();return(platform==="win32"?[venv&&resolve3(venv,"Scripts","python.exe"),resolve3(root,"venv","Scripts","python.exe"),resolve3(root,".venv","Scripts","python.exe")]:[venv&&resolve3(venv,"bin","python"),venv&&resolve3(venv,"bin","python3"),resolve3(root,"venv","bin","python"),resolve3(root,"venv","bin","python3"),resolve3(root,".venv","bin","python"),resolve3(root,".venv","bin","python3")]).find((p)=>p&&existsSync4(p))||(platform==="win32"?"python":"python3")}function asEvent(v2){if(v2&&typeof v2==="object"&&!Array.isArray(v2)&&typeof v2.type==="string")return v2;return null}function text(raw){if(typeof raw==="string")return raw;if(raw instanceof ArrayBuffer)return decoder2.decode(raw);if(ArrayBuffer.isView(raw))return decoder2.decode(raw);return null}async function lines(stream,cb){let reader=stream.getReader(),decoder3=new TextDecoder,buf="";try{while(!0){let{done,value}=await reader.read();if(done)break;buf+=decoder3.decode(value,{stream:!0});let parts=buf.split(`
|
|
3647
3647
|
`);buf=parts.pop()||"";for(let line of parts)if(line)cb(line)}if(buf.trim())cb(buf)}catch{}}class GatewayClient extends EventEmitter7{proc=null;ws=null;link=null;target=null;id=0;logs=[];pending=new Map;buf=[];exit;ok=!1;timer=null;sub=!1;root(){return hermesAgentRoot()}push(ev){if(ev.type==="gateway.ready"){if(this.ok=!0,this.timer)clearTimeout(this.timer),this.timer=null}if(this.sub)return void this.emit("event",ev);this.buf.push(ev)}log(line){if(this.logs.push(line)>LOG_MAX)this.logs.splice(0,this.logs.length-LOG_MAX)}dispatch(msg){let id=msg.id,p=id?this.pending.get(id):void 0;if(p){if(this.pending.delete(id),msg.error){let err=msg.error;p.reject(Error(typeof err?.message==="string"?err.message:"request failed"))}else p.resolve(msg.result);return}if(msg.method==="event"){let ev=asEvent(msg.params);if(ev)this.push(ev)}}fail(err){for(let p of this.pending.values())p.reject(err);this.pending.clear()}connect(raw){let cwd=process.env.HERMES_CWD||process.cwd(),url;try{url=websocketUrl(raw)}catch(err){let message=err instanceof Error?err.message:String(err);if(this.log(`[startup] websocket failed: ${message}`),this.push({type:"gateway.stderr",payload:{line:message}}),this.sub)this.emit("exit",null);else this.exit=null;return}let safe=redact(url),ws;try{ws=new WebSocket(url)}catch(err){let message=err instanceof Error?err.message:String(err);if(this.log(`[startup] websocket failed (${safe}): ${message}`),this.push({type:"gateway.stderr",payload:{line:message}}),this.sub)this.emit("exit",null);else this.exit=null;return}this.target=raw,this.ws=ws;let settled=!1;this.link=new Promise((resolve4,reject)=>{ws.addEventListener("open",()=>{if(settled)return;settled=!0,resolve4()},{once:!0}),ws.addEventListener("error",()=>{if(settled)return;settled=!0,reject(Error("gateway websocket connection failed"));try{ws.close()}catch{}},{once:!0}),ws.addEventListener("close",(event)=>{if(settled)return;settled=!0,reject(Error(`gateway websocket closed (${event.code}) during connect`))},{once:!0})}),this.link.catch(()=>{}),this.timer=setTimeout(()=>{if(this.ok||this.ws!==ws)return;this.log(`[startup] timed out (websocket=${safe}, cwd=${cwd})`),this.push({type:"gateway.start_timeout",payload:{cwd,python:"websocket"}}),this.ws=null,this.link=null,this.fail(Error("gateway websocket startup timeout"));try{ws.close()}catch{}if(this.sub)this.emit("exit",null);else this.exit=null},STARTUP_MS),ws.addEventListener("message",(event)=>{if(this.ws!==ws)return;let raw2=text(event.data);if(!raw2)return;try{this.dispatch(JSON.parse(raw2))}catch{let preview=raw2.trim().slice(0,LOG_PREVIEW)||"(empty)";this.log(`[protocol] malformed websocket: ${preview}`),this.push({type:"gateway.protocol_error",payload:{preview}})}}),ws.addEventListener("error",()=>{if(this.ws!==ws)return;let line=`websocket transport error (${safe})`;this.log(`[gateway] ${line}`),this.push({type:"gateway.stderr",payload:{line}})}),ws.addEventListener("close",(event)=>{if(this.ws!==ws)return;if(this.timer)clearTimeout(this.timer),this.timer=null;if(this.ws=null,this.link=null,this.fail(Error(`gateway websocket closed${event.code?` (${event.code})`:""}`)),this.sub)this.emit("exit",event.code);else this.exit=event.code})}start(){let raw=gatewayUrl(),root=this.root(),bin=python(root),cwd=process.env.HERMES_CWD||process.cwd(),env2={...process.env};if(!env2.TERMINAL_CWD)env2.TERMINAL_CWD=cwd;let pp=env2.PYTHONPATH?.trim();env2.PYTHONPATH=pp?`${root}${delimiter}${pp}`:root,env2.HERMES_PYTHON_SRC_ROOT=root,this.ok=!1,this.buf=[],this.exit=void 0;let restarted=!1,previous=this.proc;if(previous){this.proc=null,this.fail(Error("gateway restarted")),restarted=!0;try{previous.kill()}catch{}}let socket=this.ws;if(socket){if(this.ws=null,this.link=null,this.target=null,!restarted)this.fail(Error("gateway restarted"));try{socket.close()}catch{}}if(this.timer)clearTimeout(this.timer);if(raw){this.connect(raw);return}this.timer=setTimeout(()=>{if(this.ok)return;this.log(`[startup] timed out (python=${bin}, cwd=${cwd})`),this.push({type:"gateway.start_timeout",payload:{cwd,python:bin}});let proc2=this.proc;if(!proc2||proc2.exitCode!==null)return;try{proc2.kill()}catch(err){this.proc=null;let failure=Error(`gateway startup timeout: ${err instanceof Error?err.message:String(err)}`);if(this.fail(failure),this.sub)this.emit("exit",null);else this.exit=null}},STARTUP_MS);let proc=(()=>{try{return Bun.spawn([bin,"-u","-m","tui_gateway.entry"],{cwd,env:env2,stdin:"pipe",stdout:"pipe",stderr:"pipe"})}catch(err){if(this.timer)clearTimeout(this.timer),this.timer=null;this.proc=null;let message=err instanceof Error?err.message:String(err);if(this.log(`[startup] spawn failed: ${message}`),this.push({type:"gateway.stderr",payload:{line:message}}),this.sub)this.emit("exit",null);else this.exit=null;return null}})();if(!proc)return;if(this.proc=proc,proc.stdout)lines(proc.stdout,(raw2)=>{if(this.proc!==proc)return;try{this.dispatch(JSON.parse(raw2))}catch{let preview=raw2.trim().slice(0,LOG_PREVIEW)||"(empty)";this.log(`[protocol] malformed: ${preview}`),this.push({type:"gateway.protocol_error",payload:{preview}})}});if(proc.stderr)lines(proc.stderr,(raw2)=>{if(this.proc!==proc)return;let line=raw2.trim();if(!line)return;this.log(line),this.push({type:"gateway.stderr",payload:{line}})});proc.exited.then((code)=>{if(this.proc!==proc)return;if(this.timer)clearTimeout(this.timer),this.timer=null;if(this.fail(Error(`gateway exited${code===null?"":` (${code})`}`)),this.sub)this.emit("exit",code);else this.exit=code})}drain(){if(this.sub)return;this.sub=!0;for(let ev of this.buf.splice(0))this.emit("event",ev);if(this.exit!==void 0){let code=this.exit;this.exit=void 0,this.emit("exit",code)}}tail(n=20){return this.logs.slice(-Math.max(1,n)).join(`
|
|
3648
3648
|
`)}sid="";setSession(sid){this.sid=sid}request(method,params={}){let raw=gatewayUrl();if(raw)return this.remote(raw,method,params);if(!this.proc||this.proc.exitCode!==null)this.start();let stdin=this.proc?.stdin;if(!stdin||typeof stdin==="number")return Promise.reject(Error("gateway not running"));let rid=`r${++this.id}`,writer=stdin,merged=this.sid&¶ms.session_id===void 0?{session_id:this.sid,...params}:params;return new Promise((resolve4,reject)=>{let timeout=setTimeout(()=>{if(this.pending.delete(rid))reject(Error(`timeout: ${method}`))},REQUEST_MS);this.pending.set(rid,{reject:(e)=>{clearTimeout(timeout),reject(e)},resolve:(v2)=>{clearTimeout(timeout),resolve4(v2)}});try{let frame=encode({jsonrpc:"2.0",id:rid,method,params:merged});if(frame.issues.length){let detail=frame.issues.map((x2)=>`${x2.path}:${x2.count}`).join(", ");this.log(`[wire] sanitized invalid unicode for ${method}: ${detail}`)}writer.write(frame.text+`
|
|
@@ -4162,7 +4162,7 @@ Usage:
|
|
|
4162
4162
|
${n} mapped \xB7 ${r.skipped.length} skipped (no herm equivalent)${r.skipped.length?`:
|
|
4163
4163
|
${r.skipped.slice(0,8).join(", ")}${r.skipped.length>8?", \u2026":""}`:""}`,yes:"import"}).then((ok)=>{if(openKeys(props.dialog),!ok)return;exports_preferences.set("keys",{...exports_preferences.get("keys")??{},...r.overrides}),toast.show({variant:"success",message:`Imported ${n} \xB7 skipped ${r.skipped.length}`})})};return useKeyboard((key4)=>{if(key4.name==="up")return setSel((s)=>Math.max(0,s-1));if(key4.name==="down")return setSel((s)=>Math.min(actionRows.length-1,s+1));if(key4.name==="return"&&cur)return rebind(cur.id);if(key4.name==="r"&&!key4.ctrl&&cur?.override){write(cur.id,void 0);return}if(key4.name==="o"&&!key4.ctrl)return importOc()}),$jsxs("box",{flexDirection:"column",width:78,children:[$jsxs("box",{height:1,flexDirection:"row",children:[$jsx("box",{flexGrow:1,children:$jsx("text",{fg:theme.text,children:$jsx("strong",{children:"Keybindings"})})}),$jsx("text",{fg:theme.textMuted,children:`leader = ${keys.print("leader")}`})]}),$jsx("box",{height:1}),$jsx("scrollbox",{scrollY:!0,maxHeight:22,verticalScrollbarOptions:VBAR,children:$jsx("box",{flexDirection:"column",width:"100%",children:rows3.map((r,i)=>{if(r.type==="header")return $jsx("box",{height:1,marginTop:i>0?1:0,children:$jsx("text",{fg:theme.primary,children:$jsx("strong",{children:r.title})})},`h-${r.title}`);let ai=actionRows.findIndex((x2)=>x2.i===i),on=ai===sel,conf=conflictsWith(keys.table,r.id);return $jsxs("box",{height:1,flexDirection:"row",backgroundColor:on?theme.backgroundElement:void 0,onMouseOver:()=>setSel(ai),onMouseDown:()=>{setSel(ai),rebind(r.id)},children:[$jsx("box",{width:2,flexShrink:0,children:$jsx("text",{fg:on?theme.primary:theme.text,children:on?"\u25B8 ":" "})}),$jsx("box",{width:16,flexShrink:0,height:1,overflow:"hidden",children:$jsx("text",{fg:on?theme.accent:theme.text,children:print(r.chord,keys.print("leader"))||"\u2014"})}),$jsx("box",{flexGrow:1,minWidth:0,height:1,overflow:"hidden",children:$jsx("text",{fg:theme.textMuted,children:r.desc})}),$jsx("box",{width:5,flexShrink:0,flexDirection:"row",justifyContent:"flex-end",children:$jsxs("text",{children:[r.override?$jsx("span",{fg:theme.info,children:"\xB7 "}):null,conf.length>0?$jsx("span",{fg:theme.warning,children:"\u26A0"}):null]})})]},r.id)})})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:curConflicts.length>0?$jsx("text",{fg:theme.warning,children:`\u26A0 shares ${keys.print(cur.id)} with: ${curConflicts.join(", ")}`}):$jsx("text",{fg:theme.textMuted,children:`\u2191\u2193 select Enter rebind${cur?.override?" \xB7 r reset":""} \xB7 o import opencode \xB7 esc close \xB7 \xB7 = overridden`})})]})};function openKeys(dialog){dialog.replace($jsx(KeysDialog,{dialog}))}var ERRLIKE=/error|fail|traceback|exception|\b[45]\d\d\b|refused|denied|unauthori/i,LogsDialog=()=>{let theme=useTheme().theme,lines3=useGateway().tail(200).split(`
|
|
4164
4164
|
`).filter(Boolean);return $jsxs("box",{flexDirection:"column",width:110,height:Math.min(34,Math.max(8,lines3.length+5)),children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.primary,children:$jsx("strong",{children:"Gateway Logs"})})}),$jsx("box",{height:1,children:$jsxs("text",{fg:theme.textMuted,children:[lines3.length," lines \xB7 stderr + protocol \xB7 Esc to close"]})}),$jsx("box",{height:1}),lines3.length===0?$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"No log output captured."})}):$jsx("scrollbox",{scrollY:!0,stickyScroll:!0,stickyStart:"bottom",flexGrow:1,children:$jsx("box",{flexDirection:"column",children:lines3.map((l,i)=>$jsx("box",{height:1,children:$jsx("text",{fg:ERRLIKE.test(l)?theme.error:theme.textMuted,children:l.length>106?l.slice(0,105)+"\u2026":l})},i))})})]})},openLogs=(dialog)=>dialog.replace($jsx(LogsDialog,{}));var import_react130=__toESM(require_react_production(),1);var ThemePickerDialog=({onConfirm})=>{let ctx=useTheme(),dialog=useDialog(),options=ctx.names.map((n)=>({title:n,value:n})),onMove=import_react130.useCallback((opt)=>{ctx.set(opt.value)},[ctx]),onSelect=import_react130.useCallback((opt)=>{ctx.set(opt.value),onConfirm(),dialog.clear()},[ctx,dialog,onConfirm]),flip=import_react130.useCallback(()=>{ctx.setMode(ctx.mode==="dark"?"light":"dark")},[ctx]),onKey=import_react130.useCallback((key4)=>{if(key4.name!=="tab")return!1;return flip(),!0},[flip]),footer=$jsx("box",{height:1,onMouseDown:flip,children:$jsxs("text",{fg:ctx.theme.textMuted,children:[$jsx("span",{children:"Mode: "}),$jsx("span",{fg:ctx.mode==="light"?ctx.theme.warning:ctx.theme.accent,children:ctx.mode}),$jsx("span",{children:" \xB7 Tab/click: toggle"})]})});return $jsx(DialogSelect,{title:"Switch Theme",options,current:ctx.name,onSelect,onMove,onKey,placeholder:"Search themes...",footer})},openThemePicker=(dialog,ctx)=>{let{name:saved,mode:mode2}=ctx,confirmed=!1;dialog.replace($jsx(ThemePickerDialog,{onConfirm:()=>{confirmed=!0}}),()=>{if(confirmed)return;ctx.set(saved),ctx.setMode(mode2)})};var import_react131=__toESM(require_react_production(),1);import{homedir as homedir9}from"os";import{join as join25}from"path";var trunc6=(s,n)=>s.length<=n?s:s.slice(0,n-1)+"\u2026",defaultDirs=()=>{let hermesHome2=process.env.HERMES_HOME||join25(homedir9(),".hermes");return[BUNDLED_EIKON_DIR,join25(hermesHome2,"eikons")]},EikonPickerDialog=(props)=>{let theme=useTheme().theme,dialog=useDialog(),dirs2=props.dirs??defaultDirs(),found2=import_react131.useMemo(()=>listEikons(dirs2),[dirs2]),[cursor,setCursor]=import_react131.useState(0),cur=found2[cursor],parsed=import_react131.useMemo(()=>{if(!cur)return;try{return parseEikonFile(cur.path)}catch{return}},[cur]);useListKeys({active:!0,count:found2.length,setSel:setCursor,onActivate:()=>{if(cur)props.onSelect(cur.meta.name.toLowerCase()),dialog.clear()}});let w2=(parsed?.meta.width??48)+2,h2=Math.max(parsed?.meta.height??24,12);return $jsxs("box",{flexDirection:"column",width:40+w2,height:h2+4,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.primary,children:$jsx("strong",{children:"Pick Avatar"})})}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:`${found2.length} found \xB7 \u2191\u2193 nav \xB7 Enter select \xB7 Esc close`})}),$jsx("box",{height:1}),$jsxs("box",{flexDirection:"row",flexGrow:1,children:[$jsx("box",{width:38,marginRight:2,children:$jsx("scrollbox",{scrollY:!0,flexGrow:1,children:$jsx("box",{flexDirection:"column",width:"100%",children:found2.length===0?$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"No .eikon files found."})},"empty"):found2.map((e,i)=>{let on=i===cursor;return $jsxs("box",{flexDirection:"column",paddingLeft:1,paddingRight:1,backgroundColor:on?theme.backgroundElement:void 0,onMouseDown:()=>setCursor(i),children:[$jsx("box",{height:1,children:$jsx("text",{fg:on?theme.text:theme.textMuted,children:$jsx("strong",{children:trunc6(e.meta.name,34)})})}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:`${e.meta.author??"\u2014"} \xB7 ${e.meta.states.length} states`})})]},e.path)})})})}),$jsx("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:parsed?$jsx(AnimatedAvatar,{state:"idle",eikon:parsed},cur?.path??"none"):$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"No preview."})},"blank")})]})]})},openEikonPicker=(dialog,onSelect)=>dialog.replace($jsx(EikonPickerDialog,{onSelect}));var import_react132=__toESM(require_react_production(),1);var RollbackDialog=(props)=>{let theme=useTheme().theme,[data2,setData]=import_react132.useState(props.initial??null),[sel,setSel]=import_react132.useState(props.sel??0),[diff,setDiff]=import_react132.useState(null),[opened,setOpened]=import_react132.useState(null),[confirm,setConfirm]=import_react132.useState(!1),seq=import_react132.useRef(0),restoring=import_react132.useRef(!1);import_react132.useEffect(()=>{if(props.initial)return;props.gw.request("rollback.list").then(setData).catch((e)=>setData({enabled:!1,checkpoints:[],err:e.message}))},[props.gw,props.initial]),import_react132.useEffect(()=>()=>{seq.current++},[]);let points=data2?.checkpoints??[],cur=points[sel],target2=opened??cur,open3=(cp)=>{let id=++seq.current;props.gw.request("rollback.diff",{hash:cp.hash}).then((next2)=>{if(seq.current!==id)return;setOpened(cp),setDiff(next2)}).catch((e)=>{if(seq.current===id)props.toast.error(e)})},back=()=>{seq.current++,setDiff(null),setOpened(null),setConfirm(!1),props.dialog.replace($jsx(RollbackDialog,{gw:props.gw,toast:props.toast,dialog:props.dialog,initial:data2??void 0,sel}))},restore=(cp)=>{if(restoring.current)return;restoring.current=!0,props.gw.request("rollback.restore",{hash:cp.hash}).then((r)=>{if(!r.success)throw Error("restore rejected");let n=r.history_removed;props.toast.show({variant:"success",message:`Restored ${cp.hash.slice(0,7)}${n?` \xB7 ${n} turns removed`:""}`}),props.dialog.clear()}).catch((e)=>{props.toast.show({variant:"error",message:`Restore failed: ${e.message}`}),props.dialog.clear()}).finally(()=>{restoring.current=!1})},keys=useKeys();if(useKeyboard((key4)=>{if(diff){if(confirm){if(target2&&keys.match("dialog.confirm",key4))return restore(target2);if(keys.match("dialog.deny",key4)||keys.match("dialog.cancel",key4))return setConfirm(!1),back();return}if(keys.match("dialog.cancel",key4))return back();if(key4.name==="r")return setConfirm(!0);return}if(!data2?.enabled)return;handleListKey(keys,key4,{count:points.length,setSel,onActivate:()=>{if(cur)open3(cur)}})}),!data2)return $jsx("box",{width:60,height:3,children:$jsx("text",{fg:theme.textMuted,children:"Loading checkpoints\u2026"})});if(!data2.enabled)return $jsxs("box",{flexDirection:"column",width:60,height:5,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.warning,children:$jsx("strong",{children:data2.err?"Rollback unavailable":"Checkpoints disabled"})})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:data2.err??"Enable checkpoints in config to use /rollback."})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"Esc to close"})})]});if(diff){let body=diff.rendered||diff.diff||diff.stat||"(empty diff)";return $jsxs("box",{flexDirection:"column",width:110,height:30,children:[$jsx("box",{height:1,children:$jsxs("text",{children:[$jsx("span",{fg:theme.primary,children:$jsx("strong",{children:"Rollback \xB7 "})}),$jsx("span",{fg:theme.accent,children:target2?.hash.slice(0,7)??""}),$jsx("span",{fg:theme.textMuted,children:` ${trunc5(target2?.message??"",70)}`})]})}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:diff.stat||" "})}),$jsx("box",{height:1}),$jsx("scrollbox",{scrollY:!0,flexGrow:1,children:$jsx("box",{flexDirection:"column",width:"100%",children:$jsx(DiffBlock,{text:body})})}),$jsx("box",{height:1}),confirm?$jsx("box",{height:1,children:$jsxs("text",{children:[$jsx("span",{fg:theme.warning,children:$jsx("strong",{children:"Restore this checkpoint? "})}),$jsx("span",{fg:theme.textMuted,children:"[y] restore [n] cancel"})]})}):$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"[r] restore \xB7 Esc back"})})]})}return $jsxs("box",{flexDirection:"column",width:90,height:Math.min(28,Math.max(8,points.length+6)),children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.primary,children:$jsx("strong",{children:"Rollback"})})}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:`${points.length} checkpoints \xB7 \u2191\u2193 navigate Enter diff Esc close`})}),$jsx("box",{height:1}),points.length===0?$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"No checkpoints yet."})}):$jsx("scrollbox",{scrollY:!0,flexGrow:1,children:$jsx("box",{flexDirection:"column",width:"100%",children:points.map((cp,i)=>{let on=i===sel;return $jsx("box",{height:1,backgroundColor:on?theme.backgroundElement:void 0,onMouseDown:()=>{setSel(i),open3(cp)},onMouseOver:()=>setSel(i),children:$jsxs("text",{children:[$jsx("span",{fg:on?theme.primary:theme.textMuted,children:on?"\u25B8 ":" "}),$jsx("span",{fg:theme.accent,children:cp.hash.slice(0,7).padEnd(9)}),$jsx("span",{fg:theme.textMuted,children:ago(cp.timestamp).padEnd(12)}),$jsx("span",{fg:on?theme.text:theme.textMuted,children:trunc5(cp.message,56)})]})},cp.hash)})})})]})},openRollback=(dialog,gw,toast)=>dialog.replace($jsx(RollbackDialog,{gw,toast,dialog}));var import_react134=__toESM(require_react_production(),1);var tag=(m2,theme)=>m2.role==="user"?{label:"\u25B8 You",fg:theme.info}:m2.role==="assistant"?{label:"\u25C2 Agent",fg:theme.success}:m2.role==="tool"?{label:`\u2699 ${m2.name??"tool"}`,fg:theme.warning}:{label:"\xB7 system",fg:theme.textMuted},flatten2=(t2)=>{if(typeof t2==="string")return t2;if(!Array.isArray(t2))return"";for(let p of t2)if(p&&typeof p==="object"&&"type"in p&&p.type==="text"&&"text"in p&&typeof p.text==="string")return p.text;return""},body=(m2)=>m2.role==="tool"?m2.context??"":flatten2(m2.text),HistoryDialog=(props)=>{let theme=useTheme().theme,[rows3,setRows]=import_react134.useState(null),[err,setErr]=import_react134.useState("");import_react134.useEffect(()=>{props.gw.request("session.history").then((r)=>setRows(r.messages??[])).catch((e)=>{setErr(e.message),setRows([])})},[props.gw]);let n=rows3?.length??0,h2=Math.min(34,Math.max(8,n+5));return $jsxs("box",{flexDirection:"column",width:110,height:h2,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.primary,children:$jsx("strong",{children:"Session History"})})}),$jsx("box",{height:1,children:$jsx("text",{fg:err?theme.error:theme.textMuted,children:err?`\u26A0 ${err}`:`${n} messages \xB7 server-authoritative \xB7 Esc to close`})}),$jsx("box",{height:1}),rows3===null?$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"loading\u2026"})}):n===0?$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"Empty \u2014 no turns yet."})}):$jsx("scrollbox",{scrollY:!0,flexGrow:1,children:$jsx("box",{flexDirection:"column",children:rows3.map((m2,i)=>{let t2=tag(m2,theme);return $jsxs("box",{height:1,flexDirection:"row",children:[$jsx("box",{width:14,flexShrink:0,children:$jsx("text",{fg:t2.fg,children:trunc5(t2.label,13)})}),$jsx("box",{flexGrow:1,minWidth:0,height:1,overflow:"hidden",children:$jsx("text",{fg:m2.role==="tool"||m2.role==="system"?theme.textMuted:theme.text,children:body(m2).replace(/\n/g," ")})})]},i)})})})]})},openHistory=(dialog,gw)=>dialog.replace($jsx(HistoryDialog,{gw}));var import_react135=__toESM(require_react_production(),1);var InfoDialog=(props)=>{let theme=useTheme().theme,body2=props.rows.filter((r)=>r[1]!==void 0);return $jsxs("box",{flexDirection:"column",minWidth:52,gap:1,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.primary,children:$jsx("strong",{children:props.title})})}),props.warning?$jsx("text",{wrapMode:"word",fg:theme.warning,children:props.warning}):null,props.lines?.length?$jsx("box",{flexDirection:"column",children:props.lines.map((line4,i)=>$jsx("box",{height:1,children:$jsx("text",{fg:theme.text,children:line4})},i))}):null,$jsx("box",{flexDirection:"column",children:$jsx(KVBlock,{rows:body2})}),props.note?$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:props.note})}):null,$jsx("box",{height:1,children:$jsx("text",{fg:theme.borderSubtle,children:"Esc to close"})})]})};function openStatus(dialog,info3,sid2){let toolsets=Object.keys(info3?.tools??{}),nTools=Object.values(info3?.tools??{}).reduce((n,v2)=>n+v2.length,0),mcp=info3?.mcp_servers??[],up=mcp.filter((s)=>s.connected).length;dialog.replace($jsx(InfoDialog,{title:"Status",rows:[["Version",info3?.version||"\u2014"],["Model",info3?.model||"\u2014"],["Profile",activeProfileName()],["Home",hermesPath("")],["CWD",info3?.cwd||process.cwd()],["Session",sid2||"\u2014"],["Tools",`${nTools} in ${toolsets.length} toolset${toolsets.length===1?"":"s"}`],["Skills",String(Object.values(info3?.skills??{}).reduce((n,v2)=>n+v2.length,0))],["MCP",mcp.length?`${up}/${mcp.length} connected`:void 0]],warning:info3?.install_warning}))}var UsageDialog=({gw})=>{let theme=useTheme().theme,[u3,setU]=import_react135.useState(null),[err,setErr]=import_react135.useState("");if(import_react135.useEffect(()=>{gw.request("session.usage").then(setU).catch((e)=>setErr(e instanceof Error?e.message:String(e)))},[gw]),err)return $jsx(InfoDialog,{title:"Usage",rows:[["Error",err,theme.error]]});if(!u3)return $jsx(InfoDialog,{title:"Usage",rows:[["","\u2026"]]});let ctx=u3.context_max?`${fmt(u3.context_used??0)} / ${fmt(u3.context_max)} (${Math.round(u3.context_percent??0)}%)`:void 0;return $jsx(InfoDialog,{title:"Usage",lines:u3.credits_lines,note:u3.cost_status==="estimated"?"cost is estimated":void 0,rows:[["Model",u3.model||"\u2014"],["API calls",String(u3.calls??0)],["Input",fmt(u3.input??0)],["Output",fmt(u3.output??0)],["Cache r/w",u3.cache_read||u3.cache_write?`${fmt(u3.cache_read??0)} / ${fmt(u3.cache_write??0)}`:void 0],["Reasoning",u3.reasoning?fmt(u3.reasoning):void 0],["Total",fmt(u3.total??0)],["Context",ctx],["Cost",u3.cost_usd!=null?cost2(u3.cost_usd):void 0,theme.accent]]})},openUsage=(dialog,gw)=>dialog.replace($jsx(UsageDialog,{gw})),ProfileDialog=()=>{let[p,setP]=import_react135.useState(void 0),active=activeProfileName();if(import_react135.useEffect(()=>{listProfiles().then((ps)=>setP(ps.find((x2)=>x2.name===active)??null)).catch(()=>setP(null))},[]),p===void 0)return $jsx(InfoDialog,{title:"Profile",rows:[["","\u2026"]]});return $jsx(InfoDialog,{title:"Profile",note:p?void 0:"profile directory not found",rows:[["Active",active],["Home",p?.path??hermesPath("")],["Model",p?.model??"\u2014"],["Provider",p?.provider??"\u2014"],["Skills",p?String(p.skill_count):void 0],["Gateway",p?.gateway_running?"running":"stopped"],["Sticky",p?.is_sticky?"yes":void 0],["Alias",p?.is_default?void 0:p?.has_alias?`~/.local/bin/${active}`:"\u2014"],[".env",p?.has_env?"present":"\u2014"]]})},openProfile=(dialog)=>dialog.replace($jsx(ProfileDialog,{}));var import_react136=__toESM(require_react_production(),1);import{spawnSync as spawnSync2}from"child_process";import{existsSync as existsSync30}from"fs";var CHAFA=["/usr/sbin/chafa","/usr/bin/chafa","/usr/local/bin/chafa","/opt/homebrew/bin/chafa"];function whichChafa(){for(let p of CHAFA)if(existsSync30(p))return p;return null}function render(path4,w2,h2){let bin=whichChafa();if(!bin)return{err:"chafa not installed (brew/apt install chafa)"};let full=path4.startsWith("~")?path4.replace(/^~/,process.env.HOME??""):path4;if(!existsSync30(full))return{err:`file not found: ${full}`};let r=spawnSync2(bin,[`--size=${w2}x${h2}`,"--format=symbols","--symbols=block","--colors=full",full],{encoding:"utf8"});if(r.status!==0)return{err:r.stderr||`chafa exit ${r.status}`};return{rows:parseChafa(r.stdout)}}var ChafaDialog=({path:path4})=>{let theme=useTheme().theme,[w2]=import_react136.useState(80),[h2]=import_react136.useState(28),result=import_react136.useMemo(()=>render(path4,w2,h2),[path4,w2,h2]);return $jsxs("box",{flexDirection:"column",minWidth:w2+4,gap:1,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.primary,children:$jsxs("strong",{children:["chafa demo \xB7 ",path4]})})}),result.err?$jsx("box",{height:1,children:$jsx("text",{fg:theme.error,children:result.err})}):$jsx("box",{flexDirection:"column",children:result.rows.map((row4,i)=>$jsx("text",{children:row4.map((c,j2)=>$jsx("span",{fg:hex(c.fg),bg:hex(c.bg),children:c.ch},j2))},i))}),$jsx("box",{height:1,children:$jsxs("text",{fg:theme.borderSubtle,children:[result.rows?`${result.rows.length} rows \xB7 ${result.rows.reduce((a,r)=>a+r.length,0)} cells \xB7 `:"","Esc to close"]})})]})};function openChafa(dialog,path4){dialog.replace($jsx(ChafaDialog,{path:path4}))}var import_react138=__toESM(require_react_production(),1);var exports_selection={};__export(exports_selection,{key:()=>key4,Selection:()=>exports_selection});function yank(renderer,toast){let text5=renderer.getSelection()?.getSelectedText();if(!text5)return!1;return copyText(text5,toast).catch(()=>toast?.show({variant:"error",message:"Clipboard write failed"})),renderer.clearSelection(),!0}function key4(renderer,evt,toast){let sel=renderer.getSelection();if(!sel?.getSelectedText())return!1;if(evt.ctrl&&evt.name==="c")return yank(renderer,toast),!0;if(evt.name==="escape")return renderer.clearSelection(),!0;let focus=renderer.currentFocusedRenderable;if(focus&&sel.selectedRenderables.includes(focus))return!1;return renderer.clearSelection(),!1}var SGR_MOUSE_BLOB_RE=/^(?:\x1b\[|\^\[\[)?<?\d+(?:;\d+){1,2}[Mm]$/,SGR_MOUSE_RESIDUE_RE=/^\d+(?:;\d+){1,2}[Mm]$/;function isDegradedMouseInput(key5){return[key5.raw,key5.sequence,key5.name].some((v2)=>typeof v2==="string"&&isDegradedMouseBlob(v2))}function isDegradedMouseBlob(text5){if(!text5||/\s/.test(text5))return!1;return SGR_MOUSE_BLOB_RE.test(text5)||SGR_MOUSE_RESIDUE_RE.test(text5)}var DEFAULT_VOICE_KEY={mod:"ctrl",ch:"b",raw:"ctrl+b"},MOD_ALIASES={alt:"alt",ctrl:"ctrl",control:"ctrl",option:"alt",opt:"alt"};function parseVoiceRecordKey(raw2){if(typeof raw2!=="string"||!raw2.trim())return DEFAULT_VOICE_KEY;let lower=raw2.trim().toLowerCase(),parts2=lower.split("+").map((p)=>p.trim()).filter(Boolean);if(parts2.length<2)return DEFAULT_VOICE_KEY;if(parts2.length>2)return DEFAULT_VOICE_KEY;let[modRaw,chRaw]=parts2,mod=MOD_ALIASES[modRaw];if(!mod)return DEFAULT_VOICE_KEY;if(chRaw.length!==1)return DEFAULT_VOICE_KEY;if(mod==="ctrl"&&(chRaw==="c"||chRaw==="d"||chRaw==="l"))return DEFAULT_VOICE_KEY;return{mod,ch:chRaw,raw:lower}}function formatVoiceRecordKey(v2){return`${v2.mod[0].toUpperCase()+v2.mod.slice(1)}+${v2.ch.toUpperCase()}`}function isVoiceToggleKey(key5,configured2=DEFAULT_VOICE_KEY){if(key5.name.toLowerCase()!==configured2.ch)return!1;if(key5.shift)return!1;switch(configured2.mod){case"ctrl":return key5.ctrl&&!key5.meta&&!key5.super;case"alt":return key5.meta&&!key5.ctrl&&!key5.super}}function redraw(renderer){resolveRenderLib().clearTerminal(renderer.rendererPtr),renderer.currentRenderBuffer.clear(RGBA.fromValues(0,0,0,0)),renderer.requestRender()}var INTERRUPT_MS=5000,DOUBLE_TAB_MS=400,QUIT_MS=2000;function useAppKeys(o){let renderer=useRenderer(),keys=useKeys(),lastEsc=import_react138.useRef(0),lastTab=import_react138.useRef(0),lastQuit=import_react138.useRef(0),regionFor=(t2)=>t2===o.chatTab?"input":"content";import_react138.useEffect(()=>{let found2=conflicts(keys.table).filter((c)=>!(c.a==="session.interrupt"&&c.b==="dialog.cancel")).filter((c)=>!(c.a==="app.exit"&&c.b==="input.clear"));if(found2.length===0)return;let first=found2[0];o.onNotice(`Keybinding conflict: ${print([first.chord])} \u2192 ${first.a} and ${first.b}`+(found2.length>1?` (+${found2.length-1} more)`:""))},[keys.table]),useKeyboard((key5)=>{let c=o.composer.current;if(isDegradedMouseInput(key5)){key5.stopPropagation();return}if(exports_selection.key(renderer,key5,{show:o.onCopyToast,clear:()=>{},error:()=>{}})){key5.stopPropagation();return}if(keys.match("input.clear",key5)&&c&&!c.isEmpty()){let v2=c.value().trim();if(v2.length>=20)c.remember(v2);c.set(""),lastQuit.current=0,key5.stopPropagation();return}if(keys.match("input.stash",key5)){o.onStash(),key5.stopPropagation();return}if(keys.match("app.exit",key5)){let now=Date.now();if(now-lastQuit.current<QUIT_MS)return o.onQuit();lastQuit.current=now,o.onQuitArm(keys.print("app.exit")),key5.stopPropagation();return}if(keys.match("app.suspend",key5)){renderer.suspend(),process.kill(process.pid,"SIGTSTP"),process.once("SIGCONT",()=>renderer.resume());return}if(keys.match("app.redraw",key5)){redraw(renderer),key5.stopPropagation();return}if(keys.match("app.sidebar",key5)){o.onToggleSidebar();return}if(o.dialogOpen())return;if(o.voiceRecordKey&&o.onVoiceRecord&&isVoiceToggleKey(key5,o.voiceRecordKey)){o.onVoiceRecord(),key5.stopPropagation();return}if(c?.mode()==="shell"){if(key5.name==="escape"){c.setMode("normal"),key5.stopPropagation();return}if(key5.name==="backspace"&&!key5.ctrl&&!key5.meta&&c.caret()===0){c.setMode("normal"),key5.stopPropagation();return}}if(keys.match("session.steer",key5)){o.onSteer(),key5.stopPropagation();return}if(keys.match("queue.flush",key5)&&(o.streaming||o.starting)&&o.queued>0){o.onFlushQueue(),key5.stopPropagation();return}if(o.onPromptKey&&!keys.leader&&!key5.ctrl&&!key5.meta&&key5.eventType!=="release"){if(o.onPromptKey(key5)){key5.stopPropagation();return}}if(keys.match("editor.open",key5)&&!o.streaming){let seed=c?.value()??"";editInEditor(renderer,seed).then((out)=>{if(out===void 0){if(!process.env.VISUAL&&!process.env.EDITOR)o.onNotice("Set $EDITOR or $VISUAL to use the external editor");return}c?.set(out),o.setFocusRegion("input")}).catch((e)=>o.onNotice(e.message));return}if(keys.match("tab.prev",key5)){o.setTab((t2)=>{let n=Math.max(0,t2-1);return o.setFocusRegion(regionFor(n)),n});return}if(keys.match("tab.next",key5)){o.setTab((t2)=>{let n=Math.min(o.tabMax,t2+1);return o.setFocusRegion(regionFor(n)),n});return}if(o.subCount>0&&key5.shift&&!key5.ctrl&&!key5.meta&&key5.eventType!=="release"){if(key5.name==="left"){o.cycleSub(-1),key5.stopPropagation();return}if(key5.name==="right"){o.cycleSub(1),key5.stopPropagation();return}}if(keys.leader&&!key5.ctrl&&!key5.meta&&!key5.shift&&key5.eventType!=="release"){let n={"1":0,"2":1,"3":2,"4":3,"5":4,"6":5,"7":6,"8":7,"9":8,"0":9,"-":10}[key5.name];if(n!==void 0&&n<=o.tabMax){o.setTab(()=>{return o.setFocusRegion(regionFor(n)),n}),key5.stopPropagation();return}}if(key5.meta&&!key5.ctrl&&!key5.shift&&key5.eventType!=="release"){let n={"1":0,"2":1,"3":2,"4":3,"5":4,"6":5,"7":6,"8":7,"9":8,"0":9,"-":10}[key5.name];if(n!==void 0&&n<=o.tabMax){o.setTab(()=>{return o.setFocusRegion(regionFor(n)),n}),key5.stopPropagation();return}}if(c?.popOpen()){if(key5.name==="escape"){c.popCancel(),key5.stopPropagation();return}if(key5.name==="up"){c.popNav(-1),key5.stopPropagation();return}if(key5.name==="down"){c.popNav(1),key5.stopPropagation();return}if(key5.name==="tab"||key5.name==="return"){c.popAccept(),key5.stopPropagation();return}return}if(keys.match("focus.cycle",key5)&&!o.streaming){if(o.tab===o.chatTab){o.setFocusRegion((r)=>r==="input"?"content":"input");return}if(o.focusRegion==="input"){o.setFocusRegion("content");return}let now=Date.now();if(now-lastTab.current<DOUBLE_TAB_MS)o.setFocusRegion("input"),lastTab.current=0,key5.stopPropagation();else lastTab.current=now;return}if(keys.match("session.interrupt",key5)){if(!o.streaming&&!o.starting&&o.onEscape?.())return;if(o.streaming||o.starting){let now=Date.now();if(now-lastEsc.current<INTERRUPT_MS){o.onInterrupt(),lastEsc.current=0;return}lastEsc.current=now,o.onInterruptNotice();return}if(o.tab===o.chatTab&&o.focusRegion==="content")o.setFocusRegion("input");return}if(keys.match("reply.copy",key5))return o.onCopyLast();if(keys.match("clipboard.attach",key5)){o.onAttachClipboard(),key5.stopPropagation();return}if(o.focusRegion==="input"&&!o.streaming){if((key5.name==="!"||key5.name==="1"&&key5.shift)&&!key5.ctrl&&!key5.meta&&key5.eventType!=="release"&&c&&c.mode()==="normal"&&!c.popOpen()&&c.caret()===0){c.setMode("shell"),key5.stopPropagation();return}if(key5.name==="up"){let before=c?.value();return void(c?.historyUp()&&c?.value()!==before&&key5.stopPropagation())}if(key5.name==="down"){let before=c?.value();return void(c?.historyDown()&&c?.value()!==before&&key5.stopPropagation())}if(key5.name==="backspace"&&!key5.ctrl&&!key5.meta&&c&&(c.isEmpty()||c.caret()===0||c.value()[c.caret()-1]===`
|
|
4165
|
-
`)&&o.onDetachLast()){key5.stopPropagation();return}}if(o.tab===o.chatTab&&o.focusRegion==="content"&&!o.streaming&&!key5.ctrl&&!key5.meta&&key5.eventType!=="release"){if(key5.name.length===1&&key5.name!==" "){let ch=key5.shift&&/[a-z]/.test(key5.name)?key5.name.toUpperCase():key5.name;o.setFocusRegion("input"),c?.insert(ch),key5.stopPropagation()}}})}import{writeSync}from"fs";var done=!1;function quit(renderer,sid2,title,gw){if(done)process.exit(0);done=!0;try{gw?.kill()}catch{}if(renderer.destroy(),process.stdout.isTTY){let banner=sid2?`
|
|
4165
|
+
`)&&o.onDetachLast()){key5.stopPropagation();return}}if(o.tab===o.chatTab&&o.focusRegion==="content"&&!o.streaming&&!key5.ctrl&&!key5.meta&&key5.eventType!=="release"){if(key5.name.length===1&&key5.name!==" "){let ch=key5.shift&&/[a-z]/.test(key5.name)?key5.name.toUpperCase():key5.name;o.setFocusRegion("input"),c?.insert(ch),key5.stopPropagation()}}})}import{writeSync}from"fs";var done=!1;function quit(renderer,sid2,title,gw){if(done)process.exit(0);done=!0;try{gw?.kill()}catch{}try{renderer.setTerminalTitle("")}catch{}if(renderer.destroy(),process.stdout.isTTY){let banner=sid2?`
|
|
4166
4166
|
continue herm --resume ${sid2}${title?` \u2014 ${title.slice(0,60)}`:""}
|
|
4167
4167
|
|
|
4168
4168
|
`:`
|
|
@@ -4182,7 +4182,7 @@ ${r.skipped.slice(0,8).join(", ")}${r.skipped.length>8?", \u2026":""}`:""}`,yes:
|
|
|
4182
4182
|
${body2}`:head}function formatProcessNotification(text5){let body2=text5.replace(/^\[IMPORTANT: /,"").replace(/\]$/,""),done2=body2.match(/^Background process (\S+) completed \(exit code (\S+)\)\.\nCommand: (.+?)(?:\n|$)/);if(done2)return`${done2[1]} exited ${done2[2]} \xB7 ${done2[3]}`;let hit2=body2.match(/^Background process (\S+) matched watch pattern "([^"]+)"\.\nCommand: (.+?)(?:\n|$)/);if(hit2)return`${hit2[1]} matched "${hit2[2]}" \xB7 ${hit2[3]}`;return body2.slice(0,100)}function mapEvent(ev,side){switch(ev.type){case"gateway.ready":if(side.onReady?.(),ev.payload?.skin)side.onSkin?.(ev.payload.skin);return null;case"session.info":{let si=ev.payload;side.onSessionInfo?.(si);let label3=si.model?`Connected \u2014 ${si.model} \xB7 ${count3(si.tools)} tools \xB7 ${count3(si.skills)} skills`:"Connected to Hermes";if(si.credential_warning)side.onStatus?.(si.credential_warning);return{kind:"system",text:label3}}case"session.title":return side.onSessionTitle?.(ev.payload.session_id,ev.payload.title),null;case"message.start":return count("stream:start"),mem("stream-start"),{kind:"message.start"};case"message.delta":{let chunk=ev.payload?.text??"";if(!chunk)return null;return count("stream:chunk"),{kind:"message.delta",chunk}}case"message.complete":{count("stream:done"),mem("stream-done");let p=ev.payload;if(p?.usage)side.onUsage?.(p.usage);if(side.onTurnComplete?.(),p?.status==="error")return{kind:"error",text:p.text||"request failed \u2014 see messages above"};if(p?.status==="interrupted")return{kind:"message.complete",text:(p.text||"")+`
|
|
4183
4183
|
|
|
4184
4184
|
*[interrupted]*`,usage:p?.usage};return{kind:"message.complete",text:p?.text??void 0,usage:p?.usage}}case"tool.start":return{kind:"tool.start",id:ev.payload.tool_id,name:ev.payload.name??"unknown",preview:ev.payload.context,args:ev.payload.args_text};case"tool.progress":return{kind:"tool.progress",name:ev.payload.name,preview:ev.payload.preview};case"tool.generating":return{kind:"tool.generating",name:ev.payload.name};case"tool.complete":return{kind:"tool.complete",id:ev.payload.tool_id,summary:ev.payload.summary,error:ev.payload.error,inline_diff:ev.payload.inline_diff,duration:typeof ev.payload.duration_s==="number"?ev.payload.duration_s*1000:void 0,result:ev.payload.result_text};case"thinking.delta":return side.onStatus?.(ev.payload?.text??""),null;case"reasoning.delta":case"reasoning.available":{let text5=ev.payload?.text;if(!text5)return null;return{kind:"thinking",text:text5,final:ev.type==="reasoning.available",verbose:ev.payload?.verbose}}case"moa.reference":return{kind:"reference",text:reference(ev.payload?.label??"reference",ev.payload?.text??"",ev.payload?.index,ev.payload?.count)};case"moa.aggregating":{let agg=ev.payload?.aggregator;return side.onStatus?.(agg?`aggregating with ${agg}\u2026`:"aggregating\u2026"),null}case"subagent.start":case"subagent.thinking":case"subagent.tool":case"subagent.progress":case"subagent.complete":{let sub2=ev.type.slice(9);return record(sub2,ev.payload),{kind:"subagent",event:sub2,payload:ev.payload}}case"error":return{kind:"error",text:ev.payload?.message??"Unknown error"};case"clarify.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"clarify",...ev.payload}};case"approval.request":{let req={variant:"approval",...ev.payload},fallback={kind:"prompt",id:`approval-${pid()}`,req};if(shouldRemember(req))return side.onApprovalRemembered?.(fallback),null;return fallback}case"sudo.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"sudo",...ev.payload}};case"secret.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"secret",...ev.payload}};case"background.complete":return side.onBackground?.(ev.payload.task_id,ev.payload.text),null;case"review.summary":{let text5=String(ev.payload?.text??"").trim();if(!text5)return null;return{kind:"system",text:text5}}case"btw.complete":return side.onBtw?.(ev.payload.text),null;case"gateway.stderr":{let line4=ev.payload.line;if(/error|fail|traceback|exception|\b[45]\d\d\b|refused|denied|unauthori/i.test(line4))return{kind:"error",text:line4,fatal:!1};return null}case"skin.changed":return side.onSkin?.(ev.payload),null;case"gateway.start_timeout":return{kind:"error",text:`gateway startup timed out (${ev.payload?.python??"python"} @ ${ev.payload?.cwd??"?"})`};case"gateway.protocol_error":return{kind:"system",text:`protocol error: ${ev.payload?.preview??"?"}`};case"browser.progress":{let text5=ev.payload?.message??"";if(!text5)return null;return ev.payload?.level==="error"?{kind:"error",text:text5}:{kind:"system",text:`\xB7 ${text5}`}}case"status.update":{let kind2=ev.payload?.kind,text5=ev.payload?.text??"";if(kind2==="process")return side.onStatus?.(formatProcessNotification(text5)),null;if(side.onStatus?.(text5),!kind2||kind2==="status")return null;return{kind:"system",text:text5}}case"notification.show":if(side.notices)showNotification(side.notices,ev.payload);return null;case"notification.clear":if(side.notices)clearNotification(side.notices,ev.payload);return null;case"voice.status":{let state3=String(ev.payload?.state??"");return side.onVoiceStatus?.(state3),null}case"voice.transcript":{if(ev.payload?.no_speech_limit===!0)return side.onVoiceTranscript?.("",!0),null;let text5=String(ev.payload?.text??"").trim();if(!text5)return null;return side.onVoiceTranscript?.(text5,!1),null}}return null}var STREAM_EVENTS=new Set(["message.start","message.delta","reasoning.delta","reasoning.available","thinking.delta","moa.reference","moa.aggregating","tool.start","tool.progress","tool.generating"]),TITLE_DELAYS=[1200,5000,15000,30000];function useStream(c){let gw=useGateway(),dialog=useDialog(),toast=useToast(),bg2=useBackground(),ctx2=import_react142.useRef(c);ctx2.current=c;let timers=import_react142.useRef([]);import_react142.useEffect(()=>()=>{timers.current.forEach(clearTimeout),timers.current=[]},[]);let interrupted=import_react142.useRef(!1),info3=import_react142.useRef(!1),deltas=import_react142.useRef({text:"",think:"",timer:null}),flush2=import_react142.useCallback(()=>{let d2=deltas.current;if(d2.timer)clearTimeout(d2.timer),d2.timer=null;if(d2.think)ctx2.current.dispatch({kind:"thinking",text:d2.think,final:!1}),d2.think="";if(d2.text)ctx2.current.dispatch({kind:"message.delta",chunk:d2.text}),d2.text=""},[]),sync=import_react142.useCallback((ms2=0)=>{let sid2=ctx2.current.sidRef.current;if(!sid2)return;let run=()=>gw.request("session.title",{session_id:sid2}).then((r)=>{if(ctx2.current.sidRef.current!==sid2)return;if(ctx2.current.setTitle(r.title??""),r.session_key)set("lastSessionId",r.session_key)}).catch(()=>{});if(ms2<=0)return run();let id=setTimeout(()=>{timers.current=timers.current.filter((t2)=>t2!==id),run()},ms2);timers.current.push(id)},[gw]),retitle=import_react142.useCallback((sid2,title)=>{if(!sid2||title===void 0)return;if(sid2===ctx2.current.sidRef.current)ctx2.current.setTitle(title);home3.update("recentSessions",(rows3)=>rows3.map((r)=>r.id===sid2?{...r,title}:r))},[]),handle=import_react142.useCallback((ev)=>{let x2=ctx2.current;if(ev.type==="gateway.ready")info3.current=!1;if(ev.type==="message.start")x2.start();if(ev.type==="background.complete"&&ev.session_id&&x2.sidRef.current&&ev.session_id!==x2.sidRef.current){bg2.unregister(ev.payload.task_id);return}let shared=ev.type==="background.complete"&&!ev.session_id;if(ev.session_id&&x2.sidRef.current&&ev.session_id!==x2.sidRef.current&&!ev.type.startsWith("gateway.")&&!shared)return;if(interrupted.current){if(STREAM_EVENTS.has(ev.type))return;if(ev.type==="status.update"&&ev.payload?.kind==="lifecycle")return}let action=mapEvent(ev,{onReady:()=>{x2.session.boot(x2.launchRef.current).then((r)=>{if(x2.setSid(r.id),r.info)x2.setInfo(r.info),x2.setUsage(r.info.usage);if(x2.sessionStart.current=Date.now(),r.messages.length)x2.dispatch({kind:"load",messages:r.messages});if(r.note)toast.show({variant:"info",message:r.note})}).catch((err)=>{let msg=err instanceof Error?err.message:String(err);x2.setReady(!1),x2.setStarting(!1),x2.setStatus(`session boot failed: ${msg}`),x2.setErrorPulse(!0),x2.dispatch({kind:"system",text:`Failed to start session: ${msg}`})})},onSessionInfo:(si)=>{if(x2.setInfo(si),si.usage)x2.setUsage(si.usage);if(x2.setReady(!0),si.running===!1)x2.start(),x2.setStarting(!1),x2.setStatus("");if(si.session_id)x2.setSid(si.session_id);if(x2.settle(),si.title!==void 0)x2.setTitle(si.title);let bad=(si.mcp_servers??[]).filter((s)=>!s.connected);if(bad.length)x2.dispatch({kind:"system",text:`MCP: ${bad.length} server(s) failed to connect \u2014 ${bad.map((s)=>s.name+(s.error?` (${s.error})`:"")).join(", ")}`});gw.request("config.get",{key:"busy"}).then((r)=>{let m2=r.value;if(m2==="queue"||m2==="steer"||m2==="interrupt")x2.setBusy(m2)}).catch(()=>{})},onUsage:(u3)=>x2.setUsage(u3),onTurnComplete:()=>{x2.setStarting(!1),x2.setStatus(""),flush(gw,x2.sidRef.current),x2.goalHook.check(x2.sidRef.current),TITLE_DELAYS.forEach(sync)},onBackground:(tid,text5)=>{let title=bg2.label(tid);bg2.unregister(tid),x2.dispatch({kind:"background",id:tid,title,text:text5})},onBtw:(text5)=>{let head=text5.split(`
|
|
4185
|
-
`)[0].slice(0,80);x2.dispatch({kind:"system",text:`\u25C8 btw \u2014 ${head}`}),toast.show({variant:"info",title:"btw",message:head,duration:8000,action:{label:"view",run:()=>openAlert(dialog,"btw",text5)}})},onStatus:(text5)=>x2.setStatus(text5),onSessionTitle:retitle,onApprovalRemembered:(fallback)=>{let sid2=x2.sidRef.current;gw.request("approval.respond",{choice:"always"}).catch((err)=>{if(ctx2.current.sidRef.current!==sid2)return;x2.dispatch(fallback),toast.show({variant:"error",message:err.message})})},onSkin:(s)=>x2.setSkin(deriveSkin(s)),onVoiceStatus:x2.onVoiceStatus,onVoiceTranscript:x2.onVoiceTranscript,notices:toast});if(!action)return;if(ev.type==="session.info"){if(info3.current)return;info3.current=!0}let d2=deltas.current;if(action.kind==="message.delta"){if(d2.think)flush2();d2.text+=action.chunk,d2.timer??=setTimeout(flush2,16);return}if(action.kind==="thinking"&&!action.final){if(d2.text)flush2();d2.think+=action.text,d2.timer??=setTimeout(flush2,16);return}if(flush2(),action.kind==="message.start")x2.setStarting(!1),x2.setStatus("");if(action.kind==="error")x2.setStarting(!1);if(action.kind==="error")x2.setErrorPulse(!0);x2.dispatch(action)},[gw,dialog,toast,flush2,bg2,retitle]);useGatewayEvent(handle);let doInterrupt=import_react142.useCallback(()=>{interrupted.current=!0;let d2=deltas.current;if(d2.timer)clearTimeout(d2.timer),d2.timer=null;d2.text="",d2.think="",ctx2.current.session.interrupt().catch((err)=>{interrupted.current=!1,toast.show({variant:"error",message:err.message})})},[toast]);return{interrupted,doInterrupt}}var import_react148=__toESM(require_react_production(),1);init_perf();var PORT=Number(process.env.CONTROL_PORT)||7777,BIND=process.env.CONTROL_BIND||"127.0.0.1",enabled2=process.env.CONTROL==="1",LOOPBACK=new Set(["127.0.0.1","::1","localhost"]);function isLoopback(host){return LOOPBACK.has(host)}function warningFor(on,bind,port2){if(!on)return null;if(isLoopback(bind))return null;return{host:bind,port:port2,message:`CONTROL server bound to ${bind}:${port2} \u2014 reachable from the network. Set CONTROL_BIND=127.0.0.1 to restrict to loopback.`}}function warning(){return warningFor(enabled2,BIND,PORT)}var TAB_NAMES=TABS.map((t2)=>t2.name),bridge=null,pendingTab=null,pendingSend=!1;function setBridge(b2){bridge=b2}function currentTab(){if(pendingTab!==null)return pendingTab;return bridge?.tab()??0}var json2=(data2,status2=200)=>new Response(JSON.stringify(data2),{status:status2,headers:{"Content-Type":"application/json"}}),idx=(name)=>{let n=TAB_NAMES.indexOf(name);if(n<0)throw Error(`control.ts DANGEROUS: tab '${name}' missing from TAB_NAMES`);return n},DANGEROUS={[idx("Chat")]:new Set(["return"]),[idx("Sessions")]:new Set(["d","delete","return"]),[idx("Profiles & Automation")]:new Set(["return","space","d","delete","k"]),[idx("Config")]:new Set(["space","return","h","l","]","[","ctrl+s","d","delete"]),[idx("Eikon")]:new Set(["return","n","d","delete","s","u","ctrl+s","ctrl+u"])};function isDangerous(tab,keyName2,ctrl){let set3=DANGEROUS[tab];if(!set3)return!1;let id=ctrl?`ctrl+${keyName2}`:keyName2;return set3.has(id)}function makeKey(opts){return{name:opts.name,ctrl:opts.ctrl??!1,meta:opts.meta??!1,shift:opts.shift??!1,option:!1,sequence:opts.raw??opts.name,number:!1,raw:opts.raw??opts.name,eventType:"press",source:"raw"}}function injectKey(renderer,key5){let r=renderer;if(!r?.keyInput?.processParsedKey)return!1;return r.keyInput.processParsedKey(key5)}function getNodeChildren(n){if(n.getChildren)return n.getChildren();if(n._childrenInLayoutOrder)return[...n._childrenInLayoutOrder];return[]}function getNodeType(n){return n._type||n.tagName||n.constructor?.name||"unknown"}function buildFocusTree(node,depth=0){if(!node||typeof node!=="object")return null;let n=node,type=getNodeType(n),focused=n.focused??!1,focusable=n.focusable??!1,children2=[];if(depth<20)for(let child of getNodeChildren(n)){let c=buildFocusTree(child,depth+1);if(c)children2.push(c)}if(!(focusable||children2.some((c)=>c.focusable||c.focused||c.children.length>0))&&!focused&&depth>0)return null;let text5=n.value||n.textContent||n.text||void 0;return{type,focused,focusable,children:children2,text:text5}}function findFocused(node){if(!node||typeof node!=="object")return null;let n=node;if(n.focused)return getNodeType(n);for(let child of getNodeChildren(n)){let found2=findFocused(child);if(found2)return found2}return null}function countNodes(node){let result={total:0,focusable:0,focused:0};function walk2(n){if(!n||typeof n!=="object")return;let nd=n;if(result.total++,nd.focusable)result.focusable++;if(nd.focused)result.focused++;for(let child of getNodeChildren(nd))walk2(child)}return walk2(node),result}async function handle(req){let url2=new URL(req.url),path4=url2.pathname;if(!bridge)return json2({error:"bridge not ready"},503);if(path4==="/status"){let m2=process.memoryUsage(),tab=currentTab();return pendingTab=null,json2({tab,tabName:TAB_NAMES[tab]??"unknown",ready:bridge.ready(),streaming:bridge.streaming(),messages:bridge.messages(),session:bridge.session(),input:bridge.input(),focusRegion:bridge.focusRegion(),rss:Math.round(m2.rss/1024/1024),heap:Math.round(m2.heapUsed/1024/1024)})}let tabMatch=path4.match(/^\/tab\/(\d+)$/);if(tabMatch){let n=Number(tabMatch[1]);if(n<0||n>TAB_MAX)return json2({error:`tab 0-${TAB_MAX}`},400);let renderer=bridge.renderer();if(renderer){let cur=bridge.tab(),diff=n-cur,key5=makeKey({name:diff>0?"right":"left",meta:!0});for(let i=Math.abs(diff);i>0;i--)injectKey(renderer,key5)}else bridge.setTab(n);return pendingTab=n,json2({tab:n,tabName:TAB_NAMES[n]})}if(path4==="/send"&&req.method==="POST"){let body2=await req.json();if(!body2.message)return json2({error:"message required"},400);if(!bridge.ready())return json2({error:"not connected"},503);if(bridge.streaming())return json2({error:"already streaming"},409);if(pendingSend)return json2({error:"send already pending"},409);pendingSend=!0;try{await bridge.send(body2.message)}catch(err){return json2({error:err instanceof Error?err.message:String(err)},502)}finally{pendingSend=!1}return json2({sent:!0,message:body2.message})}if(path4==="/key"&&req.method==="POST"){let body2=await req.json();if(!body2.name)return json2({error:"name required"},400);let renderer=bridge.renderer();if(!renderer)return json2({error:"renderer not available"},503);let safe2=body2.safe!==!1,tab=currentTab();if(safe2&&isDangerous(tab,body2.name,!!body2.ctrl))return json2({error:"blocked",reason:`Key "${body2.ctrl?"ctrl+":""}${body2.name}" is dangerous on tab ${TAB_NAMES[tab]} (index ${tab}). Pass safe=false to override.`,tab,tabName:TAB_NAMES[tab]},403);let key5=makeKey({name:body2.name,ctrl:body2.ctrl,shift:body2.shift,meta:body2.meta,raw:body2.raw??(body2.name.length===1?body2.name:"")}),handled=injectKey(renderer,key5);return json2({injected:!0,handled,key:body2.name,tab,tabName:TAB_NAMES[tab]})}if(path4==="/keys"&&req.method==="POST"){let body2=await req.json();if(!body2.keys?.length)return json2({error:"keys array required"},400);let renderer=bridge.renderer();if(!renderer)return json2({error:"renderer not available"},503);let safe2=body2.safe!==!1,tab=currentTab(),delay=body2.delay??0,results=[];for(let k2 of body2.keys){if(safe2&&isDangerous(currentTab(),k2.name,!!k2.ctrl)){results.push({key:k2.name,injected:!1,handled:!1,blocked:!0});continue}let key5=makeKey({name:k2.name,ctrl:k2.ctrl,shift:k2.shift,meta:k2.meta,raw:k2.raw??(k2.name.length===1?k2.name:"")}),handled=injectKey(renderer,key5);if(results.push({key:k2.name,injected:!0,handled}),delay>0)await new Promise((r)=>setTimeout(r,delay))}return json2({results,tab,tabName:TAB_NAMES[tab]})}if(path4==="/type"&&req.method==="POST"){let body2=await req.json();if(!body2.text)return json2({error:"text required"},400);let renderer=bridge.renderer();if(!renderer)return json2({error:"renderer not available"},503);let safe2=body2.safe!==!1,tab=currentTab(),delay=body2.delay??0,count4=0;for(let ch of body2.text){if(safe2&&isDangerous(tab,ch,!1))continue;let key5=makeKey({name:ch,raw:ch});if(injectKey(renderer,key5),count4++,delay>0)await new Promise((r)=>setTimeout(r,delay))}return json2({typed:count4,total:body2.text.length,tab,tabName:TAB_NAMES[tab]})}if(path4==="/input"&&req.method==="POST"){let body2=await req.json();return bridge.setInput(body2.text??""),json2({ok:!0,text:body2.text??""})}if(path4==="/quit")return setTimeout(()=>process.exit(0),10),json2({ok:!0})
|
|
4185
|
+
`)[0].slice(0,80);x2.dispatch({kind:"system",text:`\u25C8 btw \u2014 ${head}`}),toast.show({variant:"info",title:"btw",message:head,duration:8000,action:{label:"view",run:()=>openAlert(dialog,"btw",text5)}})},onStatus:(text5)=>x2.setStatus(text5),onSessionTitle:retitle,onApprovalRemembered:(fallback)=>{let sid2=x2.sidRef.current;gw.request("approval.respond",{choice:"always"}).catch((err)=>{if(ctx2.current.sidRef.current!==sid2)return;x2.dispatch(fallback),toast.show({variant:"error",message:err.message})})},onSkin:(s)=>x2.setSkin(deriveSkin(s)),onVoiceStatus:x2.onVoiceStatus,onVoiceTranscript:x2.onVoiceTranscript,notices:toast});if(!action)return;if(ev.type==="session.info"){if(info3.current)return;info3.current=!0}let d2=deltas.current;if(action.kind==="message.delta"){if(d2.think)flush2();d2.text+=action.chunk,d2.timer??=setTimeout(flush2,16);return}if(action.kind==="thinking"&&!action.final){if(d2.text)flush2();d2.think+=action.text,d2.timer??=setTimeout(flush2,16);return}if(flush2(),action.kind==="message.start")x2.setStarting(!1),x2.setStatus("");if(action.kind==="error")x2.setStarting(!1);if(action.kind==="error")x2.setErrorPulse(!0);x2.dispatch(action)},[gw,dialog,toast,flush2,bg2,retitle]);useGatewayEvent(handle);let doInterrupt=import_react142.useCallback(()=>{interrupted.current=!0;let d2=deltas.current;if(d2.timer)clearTimeout(d2.timer),d2.timer=null;d2.text="",d2.think="",ctx2.current.session.interrupt().catch((err)=>{interrupted.current=!1,toast.show({variant:"error",message:err.message})})},[toast]);return{interrupted,doInterrupt}}var import_react148=__toESM(require_react_production(),1);init_perf();var PORT=Number(process.env.CONTROL_PORT)||7777,BIND=process.env.CONTROL_BIND||"127.0.0.1",enabled2=process.env.CONTROL==="1",LOOPBACK=new Set(["127.0.0.1","::1","localhost"]);function isLoopback(host){return LOOPBACK.has(host)}function warningFor(on,bind,port2){if(!on)return null;if(isLoopback(bind))return null;return{host:bind,port:port2,message:`CONTROL server bound to ${bind}:${port2} \u2014 reachable from the network. Set CONTROL_BIND=127.0.0.1 to restrict to loopback.`}}function warning(){return warningFor(enabled2,BIND,PORT)}var TAB_NAMES=TABS.map((t2)=>t2.name),bridge=null,pendingTab=null,pendingSend=!1;function setBridge(b2){bridge=b2}function currentTab(){if(pendingTab!==null)return pendingTab;return bridge?.tab()??0}var json2=(data2,status2=200)=>new Response(JSON.stringify(data2),{status:status2,headers:{"Content-Type":"application/json"}}),idx=(name)=>{let n=TAB_NAMES.indexOf(name);if(n<0)throw Error(`control.ts DANGEROUS: tab '${name}' missing from TAB_NAMES`);return n},DANGEROUS={[idx("Chat")]:new Set(["return"]),[idx("Sessions")]:new Set(["d","delete","return"]),[idx("Profiles & Automation")]:new Set(["return","space","d","delete","k"]),[idx("Config")]:new Set(["space","return","h","l","]","[","ctrl+s","d","delete"]),[idx("Eikon")]:new Set(["return","n","d","delete","s","u","ctrl+s","ctrl+u"])};function isDangerous(tab,keyName2,ctrl){let set3=DANGEROUS[tab];if(!set3)return!1;let id=ctrl?`ctrl+${keyName2}`:keyName2;return set3.has(id)}function makeKey(opts){return{name:opts.name,ctrl:opts.ctrl??!1,meta:opts.meta??!1,shift:opts.shift??!1,option:!1,sequence:opts.raw??opts.name,number:!1,raw:opts.raw??opts.name,eventType:"press",source:"raw"}}function injectKey(renderer,key5){let r=renderer;if(!r?.keyInput?.processParsedKey)return!1;return r.keyInput.processParsedKey(key5)}function getNodeChildren(n){if(n.getChildren)return n.getChildren();if(n._childrenInLayoutOrder)return[...n._childrenInLayoutOrder];return[]}function getNodeType(n){return n._type||n.tagName||n.constructor?.name||"unknown"}function buildFocusTree(node,depth=0){if(!node||typeof node!=="object")return null;let n=node,type=getNodeType(n),focused=n.focused??!1,focusable=n.focusable??!1,children2=[];if(depth<20)for(let child of getNodeChildren(n)){let c=buildFocusTree(child,depth+1);if(c)children2.push(c)}if(!(focusable||children2.some((c)=>c.focusable||c.focused||c.children.length>0))&&!focused&&depth>0)return null;let text5=n.value||n.textContent||n.text||void 0;return{type,focused,focusable,children:children2,text:text5}}function findFocused(node){if(!node||typeof node!=="object")return null;let n=node;if(n.focused)return getNodeType(n);for(let child of getNodeChildren(n)){let found2=findFocused(child);if(found2)return found2}return null}function countNodes(node){let result={total:0,focusable:0,focused:0};function walk2(n){if(!n||typeof n!=="object")return;let nd=n;if(result.total++,nd.focusable)result.focusable++;if(nd.focused)result.focused++;for(let child of getNodeChildren(nd))walk2(child)}return walk2(node),result}async function handle(req){let url2=new URL(req.url),path4=url2.pathname;if(!bridge)return json2({error:"bridge not ready"},503);if(path4==="/status"){let m2=process.memoryUsage(),tab=currentTab();return pendingTab=null,json2({tab,tabName:TAB_NAMES[tab]??"unknown",ready:bridge.ready(),streaming:bridge.streaming(),messages:bridge.messages(),session:bridge.session(),input:bridge.input(),focusRegion:bridge.focusRegion(),rss:Math.round(m2.rss/1024/1024),heap:Math.round(m2.heapUsed/1024/1024)})}let tabMatch=path4.match(/^\/tab\/(\d+)$/);if(tabMatch){let n=Number(tabMatch[1]);if(n<0||n>TAB_MAX)return json2({error:`tab 0-${TAB_MAX}`},400);let renderer=bridge.renderer();if(renderer){let cur=bridge.tab(),diff=n-cur,key5=makeKey({name:diff>0?"right":"left",meta:!0});for(let i=Math.abs(diff);i>0;i--)injectKey(renderer,key5)}else bridge.setTab(n);return pendingTab=n,json2({tab:n,tabName:TAB_NAMES[n]})}if(path4==="/send"&&req.method==="POST"){let body2=await req.json();if(!body2.message)return json2({error:"message required"},400);if(!bridge.ready())return json2({error:"not connected"},503);if(bridge.streaming())return json2({error:"already streaming"},409);if(pendingSend)return json2({error:"send already pending"},409);pendingSend=!0;try{await bridge.send(body2.message)}catch(err){return json2({error:err instanceof Error?err.message:String(err)},502)}finally{pendingSend=!1}return json2({sent:!0,message:body2.message})}if(path4==="/key"&&req.method==="POST"){let body2=await req.json();if(!body2.name)return json2({error:"name required"},400);let renderer=bridge.renderer();if(!renderer)return json2({error:"renderer not available"},503);let safe2=body2.safe!==!1,tab=currentTab();if(safe2&&isDangerous(tab,body2.name,!!body2.ctrl))return json2({error:"blocked",reason:`Key "${body2.ctrl?"ctrl+":""}${body2.name}" is dangerous on tab ${TAB_NAMES[tab]} (index ${tab}). Pass safe=false to override.`,tab,tabName:TAB_NAMES[tab]},403);let key5=makeKey({name:body2.name,ctrl:body2.ctrl,shift:body2.shift,meta:body2.meta,raw:body2.raw??(body2.name.length===1?body2.name:"")}),handled=injectKey(renderer,key5);return json2({injected:!0,handled,key:body2.name,tab,tabName:TAB_NAMES[tab]})}if(path4==="/keys"&&req.method==="POST"){let body2=await req.json();if(!body2.keys?.length)return json2({error:"keys array required"},400);let renderer=bridge.renderer();if(!renderer)return json2({error:"renderer not available"},503);let safe2=body2.safe!==!1,tab=currentTab(),delay=body2.delay??0,results=[];for(let k2 of body2.keys){if(safe2&&isDangerous(currentTab(),k2.name,!!k2.ctrl)){results.push({key:k2.name,injected:!1,handled:!1,blocked:!0});continue}let key5=makeKey({name:k2.name,ctrl:k2.ctrl,shift:k2.shift,meta:k2.meta,raw:k2.raw??(k2.name.length===1?k2.name:"")}),handled=injectKey(renderer,key5);if(results.push({key:k2.name,injected:!0,handled}),delay>0)await new Promise((r)=>setTimeout(r,delay))}return json2({results,tab,tabName:TAB_NAMES[tab]})}if(path4==="/type"&&req.method==="POST"){let body2=await req.json();if(!body2.text)return json2({error:"text required"},400);let renderer=bridge.renderer();if(!renderer)return json2({error:"renderer not available"},503);let safe2=body2.safe!==!1,tab=currentTab(),delay=body2.delay??0,count4=0;for(let ch of body2.text){if(safe2&&isDangerous(tab,ch,!1))continue;let key5=makeKey({name:ch,raw:ch});if(injectKey(renderer,key5),count4++,delay>0)await new Promise((r)=>setTimeout(r,delay))}return json2({typed:count4,total:body2.text.length,tab,tabName:TAB_NAMES[tab]})}if(path4==="/input"&&req.method==="POST"){let body2=await req.json();return bridge.setInput(body2.text??""),json2({ok:!0,text:body2.text??""})}if(path4==="/quit"){let renderer=bridge.renderer();try{renderer?.setTerminalTitle?.("")}catch{}return setTimeout(()=>process.exit(0),10),json2({ok:!0})}if(path4==="/focus"){let r=bridge.renderer();if(!r?.root)return json2({error:"no renderer root"},503);let counts=countNodes(r.root),tree3=buildFocusTree(r.root),focused=findFocused(r.root),currentFocus=r.currentFocusedRenderable?getNodeType(r.currentFocusedRenderable):null;return json2({focused,currentFocus,counts,tree:tree3})}if(path4==="/frame"){let r=bridge.renderer();if(!r?.currentRenderBuffer)return json2({error:"no render buffer"},503);let frame2=new TextDecoder().decode(r.currentRenderBuffer.getRealCharBytes(!0)),grep=url2.searchParams.get("grep"),body2=grep?frame2.split(`
|
|
4186
4186
|
`).filter((l)=>l.includes(grep)).join(`
|
|
4187
4187
|
`):frame2;if(url2.searchParams.get("json")==="1")return json2({frame:body2,match:grep?frame2.includes(grep):void 0,lines:frame2.split(`
|
|
4188
4188
|
`).length});return new Response(body2,{headers:{"Content-Type":"text/plain; charset=utf-8"}})}if(path4==="/logs"){let n=Number(url2.searchParams.get("n"))||200;return new Response(bridge.logs(n),{headers:{"Content-Type":"text/plain; charset=utf-8"}})}let pm=path4.match(/^\/plugin\/([^/]+)$/);if(pm&&req.method==="POST"){let body2=await req.json(),ok=await bridge.plugin(pm[1],body2.on!==!1);return json2({id:pm[1],on:body2.on!==!1,ok})}if(path4==="/push"&&req.method==="POST"){let body2=await req.json();if(!body2.type)return json2({error:"type required"},400);return bridge.push(body2),json2({pushed:body2.type})}if(path4==="/perf"){let d2=data();if(!d2)return json2({error:"PERF not enabled"},400);return json2(d2)}if(path4==="/tabs"){let ms2=Number(url2.searchParams.get("delay")||"500");for(let i=0;i<=TAB_MAX;i++)bridge.setTab(i),await new Promise((r)=>setTimeout(r,ms2));return bridge.setTab(CHAT_TAB),json2({cycled:TAB_MAX+1,delay:ms2})}if(path4==="/mem"){mem("control:snapshot");let m2=process.memoryUsage();return json2({rss:Math.round(m2.rss/1024/1024),heap:Math.round(m2.heapUsed/1024/1024),heapTotal:Math.round(m2.heapTotal/1024/1024),external:Math.round(m2.external/1024/1024)})}return json2({error:"not found",routes:["GET /status","GET /tab/:n","POST /send {message}","POST /key {name, ctrl?, shift?, meta?, raw?, safe?}","POST /keys {keys: [{name, ...}], delay?, safe?}","POST /type {text, delay?, safe?}","POST /input {text}","POST /plugin/:id {on}","POST /push {type, payload?}","GET /quit","GET /frame ?grep=pat&json=1","GET /logs ?n=200","GET /focus","GET /perf","GET /tabs","GET /mem"]},404)}function start(){if(!enabled2)return;Bun.serve({port:PORT,hostname:BIND,fetch:handle});let w2=warning();if(w2){process.stderr.write(`\x1B[33m[control] WARNING: ${w2.message}\x1B[0m
|
|
@@ -4207,10 +4207,10 @@ ${body2}`:head}function formatProcessNotification(text5){let body2=text5.replace
|
|
|
4207
4207
|
`)&&t2.cursorOffset!==0)return t2.cursorOffset=0,!0;return hist.up(),!0},historyDown:()=>{let t2=ta.current;if(!t2||modeRef.current==="shell")return!1;let buf2=live.current.input;if(buf2.indexOf(`
|
|
4208
4208
|
`,t2.cursorOffset)>=0)return!1;if(buf2.includes(`
|
|
4209
4209
|
`)&&t2.cursorOffset!==buf2.length)return t2.cursorOffset=buf2.length,!0;return hist.down(),!0}}),[hist.up,hist.down,pop3.setCursor,write]);let sidsRef=import_react156.useRef(sids);sidsRef.current=sids;let taRef=import_react156.useCallback((r)=>{if(ta.current=r,r&&!buf.current)buf.current=new PartsBuffer(r,sidsRef.current);if(!r)buf.current=null},[]),label3=!props.ready?"Connecting...":props.starting?props.status||"Starting agent...":props.streaming?props.status||"Generating...":"Ready",dot=props.ready?props.streaming?theme.warning:theme.success:theme.error,resume=resumeHint(props.subagents,props.streaming),rows3=Math.min(MAX_ROWS,Math.max(1,input.split(`
|
|
4210
|
-
`).length)),all2=props.attachments??[],previews=all2.filter((a)=>a.path&&classify(a.path)==="img").slice(0,MAX_PREVIEWS),chips=all2.filter((a)=>!previews.includes(a)).slice(0,MAX_PREVIEWS),shown=new Set([...previews,...chips]),attRows=all2.length>0?previews.length>0?2:1:0,lift=rows3+attRows+3,more=all2.filter((a)=>!shown.has(a)).length,bits=[props.hidden?.profile,props.hidden?.title,props.hidden?.place,props.hidden?.context].filter(Boolean);return $jsxs("box",{flexDirection:"column",position:"relative",children:[props.focused&&pop3.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,zIndex:2,children:$jsx(SlashPopover,{commands:pop3.popover,cursor:pop3.cursor,onCursor:pop3.setCursor,onSelect:select2})}):props.focused&&at.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,zIndex:2,children:$jsx(AtRefPopover,{items:at.items,cursor:at.cursor,onCursor:at.setCursor,onSelect:atAccept})}):props.focused&&comp.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,zIndex:2,children:$jsx(AtRefPopover,{items:comp.items,cursor:comp.cursor,onCursor:comp.setCursor,onSelect:(idx2)=>{let it=comp.items[idx2];if(it?.text)write(acceptCompletion(input,it,comp.replaceFrom,comp.replaceTo))}})}):null,(props.queue?.length??0)>0?$jsx("box",{flexDirection:"column",paddingX:1,paddingBottom:1,children:props.queue.map((q5,i)=>$jsx("box",{height:1,onMouseDown:()=>props.onDequeue?.(i),children:$jsxs("text",{children:[$jsxs("span",{fg:theme.borderSubtle,children:[i===0?"\u256D":"\u2502"," "]}),$jsxs("span",{fg:theme.textMuted,children:["\u23F8 ",i+1,". ",trunc5(q5,60)]})]})},i))}):null,$jsxs("box",{border:!0,borderStyle:"single",borderColor:mode2==="shell"?theme.primary:props.focused?theme.borderActive:theme.border,flexDirection:"column",position:"relative",children:[previews.length>0?$jsx("box",{flexDirection:"column",paddingX:1,maxHeight:MAX_PREVIEWS,overflow:"hidden",children:previews.map((a)=>$jsx(ChafaImage,{path:a.path,width:60,bare:!0},`p-${a.path}`))}):null,chips.length>0?$jsxs("box",{flexDirection:"row",flexWrap:"wrap",gap:1,paddingX:1,paddingTop:previews.length>0?0:1,paddingBottom:1,children:[chips.map((a,i)=>{if(a.path){let kind2=classify(a.path);return $jsxs("box",{flexDirection:"row",height:1,children:[$jsx(MediaChip,{path:a.path,bare:kind2==="img"}),kind2!=="img"&&a.token_estimate?$jsxs("text",{fg:theme.textMuted,children:[" ~",fmt5(a.token_estimate),"t"]}):null]},a.path)}return $jsxs("text",{children:[$jsx("span",{bg:theme.secondary,fg:theme.background,children:" file "}),$jsxs("span",{bg:theme.backgroundElement,fg:theme.textMuted,children:[" ",a.name??`file ${i+1}`," "]})]},a.name??i)}),more>0?$jsxs("text",{fg:theme.textMuted,children:["+",more]}):null]}):null,$jsxs("box",{flexDirection:"row",children:[$jsx("box",{width:1,children:$jsx("text",{fg:theme.primary,children:mode2==="shell"?"$":">"})}),$jsx("box",{width:1}),$jsx("textarea",{ref:taRef,syntaxStyle,onContentChange:()=>{let t2=ta.current;setInput(t2?.plainText??""),setCaret(t2?.cursorOffset??0)},onCursorChange:()=>{if(!live.current.input.includes("@")&&!live.current.input.includes("/"))return;let off=ta.current?.cursorOffset??0;setCaret((c)=>c===off?c:off)},onSubmit:submit4,onPaste:paste,keyBindings:bindings,wrapMode:"word",minHeight:1,maxHeight:MAX_ROWS,placeholder:mode2==="shell"?"Run a shell command (30s cap, cwd) \u2014 esc or \u232B to exit":props.streaming?"Type to queue... (Enter queues, click chip to edit)":"Message Hermes... (/ for commands, Shift+Enter for newline)",focused:props.focused,textColor:theme.text,focusedTextColor:theme.text,placeholderColor:theme.textMuted,cursorColor:theme.text,backgroundColor:"transparent",focusedBackgroundColor:"transparent",flexGrow:1})]}),pop3.ghost&&props.focused&&rows3===1&&pop3.spot?.whole?$jsx("box",{position:"absolute",top:attRows,left:2+input.length,height:1,children:$jsx("text",{fg:theme.textMuted,children:pop3.ghost})}):null]}),$jsxs("box",{height:1,flexDirection:"row",paddingX:1,children:[$jsxs("text",{children:[props.streaming?$jsx(SpinGlyph,{fg:dot}):$jsx("span",{fg:dot,children:"\u25CF"}),$jsxs("span",{fg:theme.textMuted,children:[" ",mode2==="shell"?"Shell":label3]}),mode2==="shell"?$jsx("span",{fg:theme.textMuted,children:" esc exit shell mode"}):props.starting&&props.escHint?$jsx("span",{fg:theme.warning,children:" esc again to cancel"}):props.starting?$jsx("span",{fg:theme.textMuted,children:" esc\xD72 cancel"}):props.streaming&&props.escHint?$jsx("span",{fg:theme.warning,children:" esc again to interrupt"}):props.streaming?$jsx("span",{fg:theme.textMuted,children:" esc\xD72 interrupt"}):null]}),$jsx("box",{flexGrow:1}),props.streaming&&(props.queue?.length??0)>0?$jsxs("text",{fg:theme.textMuted,children:[keys.print("queue.flush")," to send queued now "]}):null,bg2.count>0?$jsxs("text",{fg:theme.text,children:["\u25B6 ",bg2.count," "]}):null,resume?$jsxs("text",{fg:theme.textMuted,children:[resume," "]}):null,bits.length>0?$jsxs("text",{fg:theme.textMuted,children:[trunc5(bits.join(" \xB7 "),56)," "]}):null,props.model?$jsx("text",{fg:theme.textMuted,children:props.model}):null]})]})}));var import_react157=__toESM(require_react_production(),1);init_sessions_db();var normalize3=(sid2)=>sid2.trim().replace(/\.json$/i,"").replace(/^session_(?=\d{8}_)/,"");function useSession(){let gw=useGateway(),inflightMessages=(inflight)=>{let user2=String(inflight?.user??"").trim(),assistant2=String(inflight?.assistant??""),messages=[];if(user2)messages.push(...transcriptToMessages([{role:"user",text:user2}]));if(assistant2||inflight?.streaming)messages.push(...transcriptToMessages([{role:"assistant",text:assistant2}]));return messages},resume=import_react157.useCallback(async(sid2)=>{let target2=normalize3(sid2),res=await gw.request("session.resume",{session_id:target2}),id=res.session_id;gw.setSession(id),set("lastSessionId",res.resumed??target2);let messages=res.messages?.length?transcriptToMessages(res.messages):[];return{id,messages,info:res.info}},[gw]),create=import_react157.useCallback(async()=>{let res=await gw.request("session.create",{});return gw.setSession(res.session_id),{id:res.session_id,info:res.info}},[gw]),activate=import_react157.useCallback(async(sid2)=>{let target2=normalize3(sid2),res=await gw.request("session.activate",{session_id:target2}),id=res.session_id;gw.setSession(id),set("lastSessionId",res.session_key??id);let history=res.messages?.length?transcriptToMessages(res.messages):[],running2=Boolean(res.running||res.status==="working"||res.status==="waiting");return{id,info:res.info,messages:[...history,...inflightMessages(res.inflight)],running:running2,startedAt:res.started_at?res.started_at*1000:void 0,status:res.status}},[gw]),busy2=import_react157.useCallback(async()=>{try{return(await gw.request("agents.list")).processes?.some((p)=>p.status==="running")??!1}catch{return!0}},[gw]),close2=import_react157.useCallback(async(sid2,opts)=>{if(!sid2)return!1;if(opts?.preserveBackground&&await busy2())return!1;try{return await gw.request("session.close",{session_id:sid2}),!0}catch{return!1}},[gw,busy2]),boot2=import_react157.useCallback(async(launch)=>{let fresh2=async(note)=>({...await create(),messages:[],note});if(launch.mode==="resume"){let target2=launch.sid??exports_sessions_db.lastReal()?.id;if(!target2)return fresh2("no prior session to resume \u2014 starting fresh");try{return await resume(target2)}catch(e){let msg=e instanceof Error?e.message:String(e);return fresh2(`resume ${target2} failed: ${msg} \u2014 starting fresh`)}}let last4=get2("lastSessionId"),row4=last4?exports_sessions_db.byId(last4):null;if(row4?.message_count===0&&row4.parent_session_id==null)try{return await resume(row4.id)}catch{}return fresh2()},[create,resume]),interrupt=import_react157.useCallback(async()=>{await gw.request("session.interrupt")},[gw]),branch2=import_react157.useCallback(async(name)=>{return(await gw.request("session.branch",name?{name}:{})).session_id??null},[gw]),compress=import_react157.useCallback(async(arg="")=>{let raw2=arg.trim(),params=raw2?{raw_args:raw2,focus_topic:raw2}:{};return gw.request("session.compress",params)},[gw]),undo=import_react157.useCallback(async()=>{await gw.request("session.undo")},[gw]);return import_react157.useMemo(()=>({boot:boot2,create,resume,activate,close:close2,interrupt,branch:branch2,compress,undo}),[boot2,create,resume,activate,close2,interrupt,branch2,compress,undo])}init_sessions_db();init_hermes_analytics();function rehome(newHome){process.env.HERMES_HOME=newHome,setHome2(newHome),setHome(newHome),cache3.clear(),resetKanban(),close(),exports_preferences.reload(),home3.reset()}var import_react158=__toESM(require_react_production(),1);var Countdown=(p)=>{let theme=useTheme().theme,[n,setN]=import_react158.useState(p.seconds);import_react158.useEffect(()=>{if(n<=0){p.onFire();return}let t2=setTimeout(()=>setN((v2)=>v2-1),1000);return()=>clearTimeout(t2)},[n,p.onFire]),useKeyboard(()=>p.onCancel());let bar3="\u2588".repeat(n)+"\u2591".repeat(Math.max(0,p.seconds-n));return $jsxs("box",{flexDirection:"column",width:58,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.warning,children:$jsx("strong",{children:p.title})})}),$jsx("box",{height:1}),$jsx("box",{minHeight:1,children:$jsx("text",{wrapMode:"word",children:p.body})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsxs("text",{fg:theme.warning,children:[bar3," ",n,"s"]})}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:p.action})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"press any key to cancel"})})]})};function openCountdown(dialog,opts){return new Promise((resolve4)=>{dialog.replace($jsx(Countdown,{...opts,onFire:()=>{dialog.clear(),resolve4(!0)},onCancel:()=>{dialog.clear(),resolve4(!1)}}),()=>resolve4(!1))})}var SECONDS=10,SUSPEND=process.platform==="darwin"?"pmset sleepnow":"systemctl suspend",run=(cmd)=>Bun.spawn(["sh","-c",cmd],{stdout:"ignore",stderr:"ignore"}),fired=new Map;function makeGoalHook(dialog,toast){let act=(goal,done2,total)=>{let pref=(exports_preferences.get("onGoalDone")??"toast").trim(),head=goal.length>60?goal.slice(0,57)+"\u2026":goal,n=total&&total>0?` ${done2}/${total} items`:"";if(toast.show({variant:"success",title:"Goal complete",message:head+n,duration:8000}),pref==="toast")return;let cmd=pref==="suspend"?SUSPEND:pref;openCountdown(dialog,{title:"Goal complete \u2014 "+(pref==="suspend"?"suspending":"running hook"),body:head,action:`\u2192 ${cmd}`,seconds:SECONDS}).then((ok)=>{if(ok)run(cmd)})};return{check:(sid2)=>{if(!sid2)return;io.goalState(sid2).then((s)=>{if(!s||s.status!=="done")return;if(fired.get(sid2)===s.goal)return;fired.set(sid2,s.goal);let list3=s.checklist??[],done2=list3.filter((i)=>i.status==="completed"||i.status==="impossible").length;act(s.goal,done2,list3.length)}).catch(()=>{})}}}var import_react160=__toESM(require_react_production(),1);function useVoice(gw,sys){let[enabled3,setEnabled]=import_react160.useState(!1),[recording,setRecording]=import_react160.useState(!1),[processing,setProcessing]=import_react160.useState(!1),[recordKeyRaw,setRecordKeyRaw]=import_react160.useState(),[tts,setTts]=import_react160.useState(!1),[onTranscript,setTranscript]=import_react160.useState(null),pending3=import_react160.useRef(0),recordGen=import_react160.useRef(0),toggleGen=import_react160.useRef(0),setOnTranscript=import_react160.useCallback((fn)=>setTranscript(fn?()=>fn:null),[]),reset4=import_react160.useCallback(()=>{toggleGen.current++,recordGen.current++,pending3.current=0,setEnabled(!1),setRecording(!1),setProcessing(!1),setTts(!1)},[]),recordKey=import_react160.useMemo(()=>parseVoiceRecordKey(recordKeyRaw),[recordKeyRaw]),keyLabel=import_react160.useMemo(()=>formatVoiceRecordKey(recordKey),[recordKey]),state3=import_react160.useMemo(()=>({enabled:enabled3,recording,processing,recordKey,tts}),[enabled3,recording,processing,recordKey,tts]),toggle=import_react160.useCallback(async(action,sid2)=>{let current2=++toggleGen.current;try{let r=await gw("voice.toggle",{action,session_id:sid2});if(toggleGen.current!==current2)return;if(r.enabled!==void 0){if(setEnabled(r.enabled),!r.enabled)recordGen.current++,setRecording(!1),setProcessing(!1)}if(r.tts!==void 0)setTts(r.tts);if(r.record_key)setRecordKeyRaw(r.record_key);let label3=formatVoiceRecordKey(parseVoiceRecordKey(r.record_key)),ttsMsg=r.tts?" \xB7 tts on":"",details2=action==="status"&&r.details?.trim()?` \xB7 ${r.details.trim()}`:"";sys(`voice ${r.enabled?"on":"off"}${ttsMsg} [${label3}]${details2}`)}catch(e){if(toggleGen.current!==current2)return;sys(`voice: ${e instanceof Error?e.message:"gateway error"}`)}},[gw,sys]),record2=import_react160.useCallback(async(sid2)=>{if(!enabled3){sys("voice: mode is off \u2014 enable with /voice on");return}if(pending3.current)return;let current2=++recordGen.current;pending3.current=current2;let starting=!recording,action=starting?"start":"stop";if(starting)setRecording(!0);else setRecording(!1),setProcessing(!1);try{let r=await gw("voice.record",{action,session_id:sid2});if(recordGen.current!==current2)return;if(starting&&r.status!=="recording"){if(setRecording(!1),r.status==="busy")setProcessing(!0),sys("voice: still transcribing; try again shortly")}}catch(e){if(recordGen.current!==current2)return;setRecording(!starting),sys(`voice error: ${e instanceof Error?e.message:"gateway error"}`)}finally{if(pending3.current===current2)pending3.current=0}},[enabled3,recording,gw,sys]);return{state:state3,toggle,record:record2,setEnabled,setRecording,setProcessing,setRecordKey:setRecordKeyRaw,reset:reset4,keyLabel,onTranscript,setOnTranscript}}function VoiceIndicator({voice,keyLabel}){let theme=useTheme().theme;if(!voice.enabled&&!voice.recording&&!voice.processing)return null;let text5,fg2=theme.text;if(voice.recording)text5="\u25CF recording",fg2=theme.error;else if(voice.processing)text5="\u25CC transcribing",fg2=theme.warning;else text5=`voice ready [${keyLabel}]`,fg2=theme.textMuted;return $jsx("text",{children:$jsxs("span",{fg:fg2,children:[text5," "]})})}function sessionCapabilities(input){let sessionConnected=Boolean(input.sid),metadataHydrated=input.ready;return{sessionConnected,metadataHydrated,canSubmitPrompt:sessionConnected,canDispatchGatewayCommand:sessionConnected,canDrainQueue:sessionConnected&&!input.streaming}}var import_react161=__toESM(require_react_production(),1);function openMessage(dialog,m2,ops){let text5=m2.parts.filter((p)=>p.type==="text").map((p)=>p.content).join("");dialog.replace($jsx(DialogSelect,{title:"Message Actions",options:[{title:"Copy",value:"copy",description:"message text to clipboard"},{title:"Rewind here",value:"rewind",description:"undo back to this turn (destructive)"},{title:"Fork here",value:"fork",description:"branch a new session at this point"}],onSelect:(o)=>{if(dialog.clear(),o.value==="copy")return void copyText(text5,ops.toast);if(o.value==="rewind")return ops.rewind(m2);if(o.value==="fork")return ops.fork(m2)}}))}async function undo(gw,count4,sid2){for(let i=0;i<count4;i++)await gw.request("session.undo",sid2?{session_id:sid2}:{})}var textOf=(message2)=>message2.parts.filter((part)=>part.type==="text").map((part)=>part.content).join("");function useMessageActions(args){let turns=import_react161.useCallback((message2)=>{let messages=args.turn.current.messages,at=messages.findIndex((item)=>item.id===message2.id);return at<0?0:messages.slice(at).filter((item)=>item.role==="user").length},[args.turn]),rewind=import_react161.useCallback(async(message2)=>{if(args.turn.current.streaming)return!1;let count4=turns(message2);if(!count4)return!1;try{await undo(args.gw,count4);let result=await args.gw.request("session.history");return args.dispatch({kind:"load",messages:transcriptToMessages(result.messages??[])}),args.composer.current?.set(textOf(message2)),args.focus("input"),!0}catch(err){return args.toast.show({variant:"error",message:err instanceof Error?err.message:String(err)}),!1}},[args.gw,args.toast,args.turn,args.dispatch,args.composer,args.focus,turns]),fork2=import_react161.useCallback(async(message2)=>{if(args.turn.current.streaming)return;let result=await args.gw.request("session.branch",{}).catch((err)=>{return args.toast.show({variant:"error",message:`branch failed: ${err.message}`}),null});if(!result?.session_id)return;try{if(await undo(args.gw,turns(message2),result.session_id),!await args.activate(result.session_id)){await args.session.close(result.session_id);return}args.composer.current?.set(textOf(message2)),args.focus("input"),args.toast.show({variant:"success",message:`forked \u2192 ${result.title??result.session_id}`})}catch(err){await args.session.close(result.session_id),args.toast.show({variant:"error",message:err instanceof Error?err.message:String(err)})}},[args.gw,args.toast,args.turn,args.activate,args.session,args.composer,args.focus,turns]),menu=import_react161.useCallback((message2)=>{if(args.turn.current.streaming)return;openMessage(args.dialog,message2,{rewind,fork:fork2,toast:args.toast})},[args.dialog,args.toast,args.turn,rewind,fork2]);return{rewind,fork:fork2,menu}}var BUSY_RE=/session busy|waiting for model response/i,App=(props)=>$jsx(ThemeProvider,{initial:props.initialTheme,children:$jsx(GatewayProvider,{client:props.gateway,children:$jsx(ToastProvider,{children:$jsx(KeysProvider,{overrides:props.keyOverrides,children:$jsx(DialogProvider,{children:$jsx(CommandProvider,{children:$jsx(PluginProvider,{plugins:props.plugins,children:$jsx(BackgroundProvider,{children:$jsx(AppInner,{launch:props.launch??{mode:"new"}})})})})})})})})}),AppInner=({launch:launch0})=>{let gw=useGateway(),gwRestart=useGatewayRestart(),dialog=useDialog(),dialogOpen=useDialogOpen(),themeCtx=useTheme(),toast=useToast(),renderer=useRenderer(),plugins=usePlugins(),session=useSession(),dims=useTerminalDimensions(),goalHook=import_react163.useMemo(()=>makeGoalHook(dialog,toast),[dialog,toast]),[turn,dispatch]=import_react163.useReducer(turnReducer,initialTurn),[ready,setReady]=import_react163.useState(!1),[sid2,setSid]=import_react163.useState(""),sidRef=import_react163.useRef(sid2);sidRef.current=sid2;let[starting,setStarting]=import_react163.useState(!1),startRef=import_react163.useRef(starting);startRef.current=starting;let active=turn.streaming||starting,capabilities=sessionCapabilities({sid:sid2,ready,streaming:active}),[tab,setTab]=import_react163.useState(CHAT_TAB),[subTabs,setSubTabs]=import_react163.useState(()=>({[SESSIONS_TAB]:0,[AUTOMATION_TAB]:0,[CONFIG_TAB]:0,[EIKON_TAB]:0})),setSub=import_react163.useCallback((tabIdx,sub2)=>setSubTabs((prev)=>prev[tabIdx]===sub2?prev:{...prev,[tabIdx]:sub2}),[]),sessSub=import_react163.useCallback((i)=>setSub(SESSIONS_TAB,i),[setSub]),autoSub=import_react163.useCallback((i)=>setSub(AUTOMATION_TAB,i),[setSub]),cfgSub=import_react163.useCallback((i)=>setSub(CONFIG_TAB,i),[setSub]),eikSub=import_react163.useCallback((i)=>setSub(EIKON_TAB,i),[setSub]),[hideSidebar,setHideSidebar]=import_react163.useState(!1),[usage,setUsage]=import_react163.useState(void 0),[info3,setInfo]=import_react163.useState(null),[title,setTitle]=import_react163.useState(""),caption=title.trim(),titleRef=import_react163.useRef(caption);titleRef.current=caption,import_react163.useEffect(()=>{process.removeAllListeners("SIGINT"),process.on("SIGINT",()=>quit(renderer,sidRef.current,titleRef.current,gw))},[renderer,gw]),import_react163.useEffect(()=>{let w2=warning();if(!w2)return;toast.show({variant:"warning",title:"control server exposed",message:w2.message,duration:15000})},[toast]);let[focusRegion,setFocusRegion]=import_react163.useState("input"),goToTab=import_react163.useCallback((t2)=>{setTab(t2),setFocusRegion(t2===CHAT_TAB?"input":"content")},[]),goTo=import_react163.useCallback((t2,sub2)=>{setTab(t2),setSubTabs((prev)=>prev[t2]===sub2?prev:{...prev,[t2]:sub2}),setFocusRegion(t2===CHAT_TAB?"input":"content")},[]),[status2,setStatus]=import_react163.useState(""),[escHint,setEscHint]=import_react163.useState(!1),[eikon,setEikon]=import_react163.useState(void 0),[queue,setQueue]=import_react163.useState([]),[busy2,setBusy]=import_react163.useState("queue"),turnRef=import_react163.useRef(turn);turnRef.current=turn;let queueRef=import_react163.useRef(queue);queueRef.current=queue;let launchRef=import_react163.useRef(launch0),launch=launchRef.current,[splash,setSplash]=import_react163.useState(launch.splash!==!1),[switching,setSwitching]=import_react163.useState(!1),summoned=import_react163.useRef(!1),creating=import_react163.useRef(!1),[composing,setComposing]=import_react163.useState(!1),splashLast=import_react163.useMemo(()=>launch.mode==="new"?lastReal():void 0,[launch.mode]),splashInfo=import_react163.useMemo(()=>info3?{agentVersion:info3.version,behind:info3.update_behind,model:info3.model}:void 0,[info3?.version,info3?.update_behind,info3?.model]),splashLastProp=import_react163.useMemo(()=>splashLast?{id:splashLast.id,title:splashLast.title}:void 0,[splashLast]),news=import_react163.useMemo(()=>readChangelog()?.headline,[]),[attachments,setAttachments]=import_react163.useState([]),attachmentsRef=import_react163.useRef(attachments);attachmentsRef.current=attachments;let[cloudH,setCloudH]=import_react163.useState(CLOUD_MIN),[pick2,setPick]=import_react163.useState(void 0),[skin2,setSkin]=import_react163.useState(()=>deriveSkin(void 0)),inflight=import_react163.useRef(!1),hold=import_react163.useRef(!1),pending3=import_react163.useRef(!1),detaching=import_react163.useRef(0),[pulse,setPulse]=import_react163.useState(0),start2=import_react163.useCallback(()=>{inflight.current=!1,pending3.current=!1,setPulse((n)=>n+1)},[]),settle=import_react163.useCallback(()=>{if(!hold.current)return;hold.current=!1,setPulse((n)=>n+1)},[]),undone=import_react163.useRef([]),sessionStart=import_react163.useRef(Date.now()),composer2=import_react163.useRef(null),promptRef=import_react163.useRef(null),{cmds}=useSlashCommands(),cmdsRef=import_react163.useRef(cmds);cmdsRef.current=cmds;let sys=import_react163.useCallback((text5)=>dispatch({kind:"system",text:text5}),[]),voice=useVoice(gw.request.bind(gw),sys);import_react163.useEffect(()=>{voice.setOnTranscript((text5)=>{let c=composer2.current;if(!c)return;c.set(""),setTimeout(()=>sendRef.current(text5),0)})},[]);let[errorPulse,setErrorPulse]=import_react163.useState(!1);import_react163.useEffect(()=>{let restart=(mode2="resume")=>{let sid3=sidRef.current;if(mode2==="resume"&&sid3)launchRef.current={mode:"resume",sid:sid3,splash:!1};gw.setSession(""),setReady(!1),setStarting(!1),setStatus("gateway restarting"),voice.reset()},exit=(code2)=>{let text5=`gateway exited${code2===null?"":` (${code2})`}`,sid3=sidRef.current;if(sid3)launchRef.current={mode:"resume",sid:sid3,splash:!1};gw.setSession(""),setReady(!1),setStarting(!1),setStatus(text5),setErrorPulse(!0),voice.reset(),dispatch({kind:"system",text:text5})};return gw.on("restart",restart),gw.on("exit",exit),()=>{gw.off("restart",restart),gw.off("exit",exit)}},[gw]);let agentState=errorPulse?"error":turn.toolActive?"working":turn.streaming&&turn.hasContent?"speaking":active?"thinking":composing?"listening":"idle",onAvatarHold=import_react163.useCallback((s)=>{if(s==="error")setErrorPulse(!1)},[]),prompt=import_react163.useMemo(()=>pending2(turn.messages),[turn.messages]),cloudAuto=turn.streaming&&!turn.hasContent&&!prompt,[force,setForce]=import_react163.useState(void 0),cloud=!prompt&&(force??cloudAuto),prevStream=import_react163.useRef(turn.streaming);import_react163.useEffect(()=>{if(!prevStream.current&&turn.streaming)setForce(void 0),setPick(void 0);prevStream.current=turn.streaming},[turn.streaming]);let onPick=import_react163.useCallback((m2)=>{setPick((p)=>{if(m2&&p&&m2.id===p.id){setForce(!1);return}return setForce(!!m2),m2})},[]),onAvatar=import_react163.useCallback(()=>{let next2=!cloud;if(!next2)setPick(void 0);setForce(next2)},[cloud]),closeCloud=import_react163.useCallback(()=>{setForce(!1),setPick(void 0)},[]),intr=import_react163.useRef(()=>{}),steer=import_react163.useCallback((text5)=>{let v2=text5.trim();if(!v2)return;gw.request("session.steer",{text:v2}).then((r)=>toast.show(r.status==="queued"?{variant:"success",message:"Queued \u2014 lands on next tool result"}:{variant:"info",message:"No turn running; send as a normal message"})).catch((e)=>toast.show({variant:"error",message:e.message}))},[gw,toast]),openSteer=import_react163.useCallback(()=>{openTextPrompt(dialog,{title:"Steer active turn",label:"Soft nudge for the running session"}).then((v2)=>{if(v2)steer(v2)})},[dialog,steer]),onEnqueue=import_react163.useCallback((t2)=>{if(busy2==="steer"){let v2=t2.trim();if(!v2)return;gw.request("session.steer",{text:v2}).then((r)=>{if(r.status==="queued")return toast.show({variant:"success",message:"Queued \u2014 lands on next tool result"});setQueue((q5)=>[...q5,t2]),toast.show({variant:"info",message:"steer rejected \u2014 queued for next turn"})}).catch(()=>setQueue((q5)=>[...q5,t2]));return}if(busy2==="interrupt"){hold.current=!0,setQueue((q5)=>[t2,...q5]),intr.current();return}setQueue((q5)=>[...q5,t2])},[busy2,gw,toast]),updateAttachments=import_react163.useCallback((next2)=>{let value2=typeof next2==="function"?next2(attachmentsRef.current):next2;attachmentsRef.current=value2,setAttachments(value2)},[]),onAttach=import_react163.useCallback((r)=>updateAttachments((a)=>[...a,r]),[updateAttachments]),stream=useStream({dispatch,session,launchRef,sidRef,sessionStart,goalHook,setSid,setInfo,setReady,setTitle,setBusy,setStarting,setUsage,setStatus,setSkin,setErrorPulse,settle,onVoiceStatus:(state3)=>{voice.setRecording(state3==="listening"||state3==="recording"),voice.setProcessing(state3==="transcribing"||state3==="processing")},onVoiceTranscript:(text5,noSpeechLimit)=>{if(voice.setRecording(!1),voice.setProcessing(!1),noSpeechLimit){voice.setEnabled(!1),sys("voice: disabled after repeated silence");return}voice.onTranscript?.(text5)},start:start2}),interrupt=import_react163.useCallback(()=>{if(startRef.current&&!turnRef.current.streaming)hold.current=!0;stream.doInterrupt()},[stream.doInterrupt]);intr.current=interrupt;let reset4=import_react163.useCallback(()=>{stream.interrupted.current=!1,hold.current=!1,pending3.current=!1,toast.clear("credits.depleted"),undone.current=[],dispatch({kind:"reset"}),setUsage(void 0),setReady(!1),setStarting(!1),setStatus(""),setTitle(""),updateAttachments([])},[toast,updateAttachments]),newSession=import_react163.useCallback(async()=>{if(creating.current)return;creating.current=!0,setSwitching(!0);let prev=sidRef.current;summoned.current=!0,setSplash(!0),setReady(!1),gw.setSession("");try{let r=await session.create();if(reset4(),setSid(r.id),r.info)setInfo(r.info),setUsage(r.info.usage);if(setReady(!0),setStarting(!1),setStatus(""),sessionStart.current=Date.now(),prev)session.close(prev,{preserveBackground:!0})}catch(err){if(prev)gw.setSession(prev),setReady(!0);setSplash(!1),summoned.current=!1,dispatch({kind:"system",text:`Failed to create session: ${err instanceof Error?err.message:String(err)}`})}finally{creating.current=!1,setSwitching(!1)}},[reset4,session,gw]),switchSession=import_react163.useCallback(async(target2)=>{let prev=sidRef.current;summoned.current=!0,setSplash(!0),setSwitching(!0),gw.setSession(""),setSid(""),goToTab(CHAT_TAB);try{let res=await session.resume(target2);if(reset4(),setSid(res.id),res.info)setInfo(res.info),setUsage(res.info.usage);if(setReady(!0),sessionStart.current=Date.now(),res.messages.length)dispatch({kind:"load",messages:res.messages});if(prev&&prev!==res.id)session.close(prev,{preserveBackground:!0});setSplash(!1),summoned.current=!1}catch(err){if(prev)gw.setSession(prev),setSid(prev),setReady(!0);dispatch({kind:"system",text:`Failed to resume: ${err instanceof Error?err.message:String(err)}`}),setSplash(!1),summoned.current=!1}finally{setSwitching(!1)}},[reset4,session,goToTab,gw]),liveStatus=(state3,running2=!1)=>{if(state3==="waiting")return"waiting for input\u2026";if(state3==="starting")return"starting agent\u2026";return running2||state3==="working"?"running\u2026":"ready"},activateSession=import_react163.useCallback(async(target2)=>{let prev=sidRef.current;summoned.current=!0,setSplash(!0),setSwitching(!0),gw.setSession(""),setSid(""),goToTab(CHAT_TAB);try{let res=await session.activate(target2);if(reset4(),setSid(res.id),res.info)setInfo(res.info),setUsage(res.info.usage);if(sessionStart.current=res.startedAt??Date.now(),dispatch({kind:"load.live",messages:res.messages,streaming:res.running}),setStatus(liveStatus(res.status,res.running)),setReady(!0),setSplash(!1),summoned.current=!1,prev&&prev!==res.id)toast.show({variant:"info",message:"switched live session"});return!0}catch(err){if(prev)gw.setSession(prev),setSid(prev),setReady(!0);return dispatch({kind:"system",text:`Failed to activate: ${err instanceof Error?err.message:String(err)}`}),setSplash(!1),summoned.current=!1,!1}finally{setSwitching(!1)}},[reset4,session,goToTab,toast,gw]),switchProfile=import_react163.useCallback((newHome,name)=>{voice.reset(),rehome(newHome),reset4(),gw.setSession(""),setSid(""),setInfo(null),setSkin(deriveSkin(void 0)),summoned.current=!0,setSplash(!0),launchRef.current={mode:"new",splash:!0},toast.show({variant:"info",message:`Switching to '${name}'\u2026`}),goToTab(CHAT_TAB),gwRestart("new")},[reset4,goToTab,gwRestart,toast,gw]),loadEikon=import_react163.useCallback((path4)=>{try{setEikon(parseEikonFile(path4))}catch{setEikon(void 0)}},[]),eikonName=usePref("eikon"),eikonRev=import_react163.useSyncExternalStore(exports_eikon.onRevision,exports_eikon.revision);import_react163.useEffect(()=>{let p=eikonName&&exports_eikon.baked(eikonName)||bundledEikonPath(skin2.skin?.name);if(p)loadEikon(p);else setEikon(void 0)},[eikonName,eikonRev,skin2.skin?.name,loadEikon]);let messageActions=useMessageActions({gw,dialog,toast,session,activate:activateSession,composer:composer2,turn:turnRef,dispatch,focus:setFocusRegion}),rewind=messageActions.rewind,msgMenu=messageActions.menu,attachClipboard=import_react163.useCallback(()=>{gw.request("clipboard.paste").then((r)=>r.attached?updateAttachments((a)=>[...a,r]):toast.show({variant:"info",message:r.message??"No image in clipboard"})).catch((e)=>toast.show({variant:"error",message:e.message}))},[gw,toast,updateAttachments]),sendRef=import_react163.useRef(()=>{}),slash3=useSlash({dispatch,session,turnRef,queueRef,sendRef,composer:composer2,summoned,undone,capabilities,info:info3,sid:sid2,title:caption,skin:skin2,setQueue,setFocusRegion,setSplash,setAttachments:updateAttachments,setInfo,setUsage,setTitle,newSession,switchSession,activateSession,rewind,goTo,attachClipboard,voiceToggle:voice.toggle}),send=import_react163.useCallback(async(raw2)=>{if(creating.current)return;if(["exit","quit",":q",":q!",":wq"].includes(raw2.trim()))return quit(renderer,sidRef.current,titleRef.current,gw);if(detaching.current>0){if(raw2.trim())composer2.current?.set(raw2);setStatus("detaching image\u2026");return}let m2=raw2.match(/^\/(\S+)(?:\s+([\s\S]*))?$/);if(m2){let[,name,arg=""]=m2,r=resolve9(cmdsRef.current,name);if("hit"in r)return slash3(r.hit,arg.trim());if("ambiguous"in r){let head=r.ambiguous.slice(0,6).join(", ");return dispatch({kind:"system",text:`ambiguous: /${name} \u2192 ${head}${r.ambiguous.length>6?", \u2026":""}`})}}let text5=raw2;if(hasInterp(raw2))setStatus("interpolating\u2026"),text5=await interpolate(gw,raw2),setStatus("");stream.interrupted.current=!1;let att=attachmentsRef.current,withMedia=att.length?[...att.flatMap((a)=>a.path?[`MEDIA:${a.path}`]:[]),text5].filter(Boolean).join(`
|
|
4211
|
-
`):text5;if(pending3.current){setQueue((q5)=>[...q5,raw2]),setStatus("queued for next turn");return}pending3.current=!0,setPulse((n)=>n+1),gw.request("prompt.submit",{text:text5}).then((r)=>{if(dispatch({kind:"user",text:withMedia}),r.status==="streaming"&&!turnRef.current.streaming)setStarting(!0),setStatus("starting agent\u2026");updateAttachments([]),undone.current=[],setTab(CHAT_TAB)}).catch((e)=>{let msg=e instanceof Error?e.message:String(e);if(BUSY_RE.test(msg)){pending3.current=!1,setPulse((n)=>n+1),inflight.current=!0,setQueue((q5)=>[text5,...q5]),setStatus("queued for next turn"),toast.show({variant:"info",message:"queued for next turn"}),setTimeout(()=>{inflight.current=!1,setPulse((n)=>n+1)},400);return}pending3.current=!1,setPulse((n)=>n+1),inflight.current=!1,setStarting(!1),dispatch({kind:"system",text:`submit failed: ${msg}`}),toast.show({variant:"error",message:msg})})},[gw,slash3,toast,updateAttachments]);sendRef.current=send;let onShell=
|
|
4210
|
+
`).length)),all2=props.attachments??[],previews=all2.filter((a)=>a.path&&classify(a.path)==="img").slice(0,MAX_PREVIEWS),chips=all2.filter((a)=>!previews.includes(a)).slice(0,MAX_PREVIEWS),shown=new Set([...previews,...chips]),attRows=all2.length>0?previews.length>0?2:1:0,lift=rows3+attRows+3,more=all2.filter((a)=>!shown.has(a)).length,bits=[props.hidden?.profile,props.hidden?.title,props.hidden?.place,props.hidden?.context].filter(Boolean);return $jsxs("box",{flexDirection:"column",position:"relative",children:[props.focused&&pop3.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,zIndex:2,children:$jsx(SlashPopover,{commands:pop3.popover,cursor:pop3.cursor,onCursor:pop3.setCursor,onSelect:select2})}):props.focused&&at.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,zIndex:2,children:$jsx(AtRefPopover,{items:at.items,cursor:at.cursor,onCursor:at.setCursor,onSelect:atAccept})}):props.focused&&comp.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,zIndex:2,children:$jsx(AtRefPopover,{items:comp.items,cursor:comp.cursor,onCursor:comp.setCursor,onSelect:(idx2)=>{let it=comp.items[idx2];if(it?.text)write(acceptCompletion(input,it,comp.replaceFrom,comp.replaceTo))}})}):null,(props.queue?.length??0)>0?$jsx("box",{flexDirection:"column",paddingX:1,paddingBottom:1,children:props.queue.map((q5,i)=>$jsx("box",{height:1,onMouseDown:()=>props.onDequeue?.(i),children:$jsxs("text",{children:[$jsxs("span",{fg:theme.borderSubtle,children:[i===0?"\u256D":"\u2502"," "]}),$jsxs("span",{fg:theme.textMuted,children:["\u23F8 ",i+1,". ",trunc5(q5,60)]})]})},i))}):null,$jsxs("box",{border:!0,borderStyle:"single",borderColor:mode2==="shell"?theme.primary:props.focused?theme.borderActive:theme.border,flexDirection:"column",position:"relative",children:[previews.length>0?$jsx("box",{flexDirection:"column",paddingX:1,maxHeight:MAX_PREVIEWS,overflow:"hidden",children:previews.map((a)=>$jsx(ChafaImage,{path:a.path,width:60,bare:!0},`p-${a.path}`))}):null,chips.length>0?$jsxs("box",{flexDirection:"row",flexWrap:"wrap",gap:1,paddingX:1,paddingTop:previews.length>0?0:1,paddingBottom:1,children:[chips.map((a,i)=>{if(a.path){let kind2=classify(a.path);return $jsxs("box",{flexDirection:"row",height:1,children:[$jsx(MediaChip,{path:a.path,bare:kind2==="img"}),kind2!=="img"&&a.token_estimate?$jsxs("text",{fg:theme.textMuted,children:[" ~",fmt5(a.token_estimate),"t"]}):null]},a.path)}return $jsxs("text",{children:[$jsx("span",{bg:theme.secondary,fg:theme.background,children:" file "}),$jsxs("span",{bg:theme.backgroundElement,fg:theme.textMuted,children:[" ",a.name??`file ${i+1}`," "]})]},a.name??i)}),more>0?$jsxs("text",{fg:theme.textMuted,children:["+",more]}):null]}):null,$jsxs("box",{flexDirection:"row",children:[$jsx("box",{width:1,children:$jsx("text",{fg:theme.primary,children:mode2==="shell"?"$":">"})}),$jsx("box",{width:1}),$jsx("textarea",{ref:taRef,syntaxStyle,onContentChange:()=>{let t2=ta.current;setInput(t2?.plainText??""),setCaret(t2?.cursorOffset??0)},onCursorChange:()=>{if(!live.current.input.includes("@")&&!live.current.input.includes("/"))return;let off=ta.current?.cursorOffset??0;setCaret((c)=>c===off?c:off)},onSubmit:submit4,onPaste:paste,keyBindings:bindings,wrapMode:"word",minHeight:1,maxHeight:MAX_ROWS,placeholder:mode2==="shell"?"Run a shell command (30s cap, cwd) \u2014 esc or \u232B to exit":props.streaming?"Type to queue... (Enter queues, click chip to edit)":"Message Hermes... (/ for commands, Shift+Enter for newline)",focused:props.focused,textColor:theme.text,focusedTextColor:theme.text,placeholderColor:theme.textMuted,cursorColor:theme.text,backgroundColor:"transparent",focusedBackgroundColor:"transparent",flexGrow:1})]}),pop3.ghost&&props.focused&&rows3===1&&pop3.spot?.whole?$jsx("box",{position:"absolute",top:attRows,left:2+input.length,height:1,children:$jsx("text",{fg:theme.textMuted,children:pop3.ghost})}):null]}),$jsxs("box",{height:1,flexDirection:"row",paddingX:1,children:[$jsxs("text",{children:[props.streaming?$jsx(SpinGlyph,{fg:dot}):$jsx("span",{fg:dot,children:"\u25CF"}),$jsxs("span",{fg:theme.textMuted,children:[" ",mode2==="shell"?"Shell":label3]}),mode2==="shell"?$jsx("span",{fg:theme.textMuted,children:" esc exit shell mode"}):props.starting&&props.escHint?$jsx("span",{fg:theme.warning,children:" esc again to cancel"}):props.starting?$jsx("span",{fg:theme.textMuted,children:" esc\xD72 cancel"}):props.streaming&&props.escHint?$jsx("span",{fg:theme.warning,children:" esc again to interrupt"}):props.streaming?$jsx("span",{fg:theme.textMuted,children:" esc\xD72 interrupt"}):null]}),$jsx("box",{flexGrow:1}),props.streaming&&(props.queue?.length??0)>0?$jsxs("text",{fg:theme.textMuted,children:[keys.print("queue.flush")," to send queued now "]}):null,bg2.count>0?$jsxs("text",{fg:theme.text,children:["\u25B6 ",bg2.count," "]}):null,resume?$jsxs("text",{fg:theme.textMuted,children:[resume," "]}):null,bits.length>0?$jsxs("text",{fg:theme.textMuted,children:[trunc5(bits.join(" \xB7 "),56)," "]}):null,props.model?$jsx("text",{fg:theme.textMuted,children:props.model}):null]})]})}));var import_react157=__toESM(require_react_production(),1);init_sessions_db();var normalize3=(sid2)=>sid2.trim().replace(/\.json$/i,"").replace(/^session_(?=\d{8}_)/,"");function useSession(){let gw=useGateway(),inflightMessages=(inflight)=>{let user2=String(inflight?.user??"").trim(),assistant2=String(inflight?.assistant??""),messages=[];if(user2)messages.push(...transcriptToMessages([{role:"user",text:user2}]));if(assistant2||inflight?.streaming)messages.push(...transcriptToMessages([{role:"assistant",text:assistant2}]));return messages},resume=import_react157.useCallback(async(sid2)=>{let target2=normalize3(sid2),res=await gw.request("session.resume",{session_id:target2}),id=res.session_id;gw.setSession(id),set("lastSessionId",res.resumed??target2);let messages=res.messages?.length?transcriptToMessages(res.messages):[];return{id,messages,info:res.info}},[gw]),create=import_react157.useCallback(async()=>{let res=await gw.request("session.create",{});return gw.setSession(res.session_id),{id:res.session_id,info:res.info}},[gw]),activate=import_react157.useCallback(async(sid2)=>{let target2=normalize3(sid2),res=await gw.request("session.activate",{session_id:target2}),id=res.session_id;gw.setSession(id),set("lastSessionId",res.session_key??id);let history=res.messages?.length?transcriptToMessages(res.messages):[],running2=Boolean(res.running||res.status==="working"||res.status==="waiting");return{id,info:res.info,messages:[...history,...inflightMessages(res.inflight)],running:running2,startedAt:res.started_at?res.started_at*1000:void 0,status:res.status}},[gw]),busy2=import_react157.useCallback(async()=>{try{return(await gw.request("agents.list")).processes?.some((p)=>p.status==="running")??!1}catch{return!0}},[gw]),close2=import_react157.useCallback(async(sid2,opts)=>{if(!sid2)return!1;if(opts?.preserveBackground&&await busy2())return!1;try{return await gw.request("session.close",{session_id:sid2}),!0}catch{return!1}},[gw,busy2]),boot2=import_react157.useCallback(async(launch)=>{let fresh2=async(note)=>({...await create(),messages:[],note});if(launch.mode==="resume"){let target2=launch.sid??exports_sessions_db.lastReal()?.id;if(!target2)return fresh2("no prior session to resume \u2014 starting fresh");try{return await resume(target2)}catch(e){let msg=e instanceof Error?e.message:String(e);return fresh2(`resume ${target2} failed: ${msg} \u2014 starting fresh`)}}let last4=get2("lastSessionId"),row4=last4?exports_sessions_db.byId(last4):null;if(row4?.message_count===0&&row4.parent_session_id==null)try{return await resume(row4.id)}catch{}return fresh2()},[create,resume]),interrupt=import_react157.useCallback(async()=>{await gw.request("session.interrupt")},[gw]),branch2=import_react157.useCallback(async(name)=>{return(await gw.request("session.branch",name?{name}:{})).session_id??null},[gw]),compress=import_react157.useCallback(async(arg="")=>{let raw2=arg.trim(),params=raw2?{raw_args:raw2,focus_topic:raw2}:{};return gw.request("session.compress",params)},[gw]),undo=import_react157.useCallback(async()=>{await gw.request("session.undo")},[gw]);return import_react157.useMemo(()=>({boot:boot2,create,resume,activate,close:close2,interrupt,branch:branch2,compress,undo}),[boot2,create,resume,activate,close2,interrupt,branch2,compress,undo])}var import_react158=__toESM(require_react_production(),1);function useTerminalTitle(active,cwd){let renderer=useRenderer();import_react158.useEffect(()=>{let title=active?"\u25CF Herm":"Herm",name=cwd?.split(/[\\/]/).filter(Boolean).at(-1);renderer.setTerminalTitle(name?`${title} \xB7 ${name}`:title)},[renderer,active,cwd])}init_sessions_db();init_hermes_analytics();function rehome(newHome){process.env.HERMES_HOME=newHome,setHome2(newHome),setHome(newHome),cache3.clear(),resetKanban(),close(),exports_preferences.reload(),home3.reset()}var import_react160=__toESM(require_react_production(),1);var Countdown=(p)=>{let theme=useTheme().theme,[n,setN]=import_react160.useState(p.seconds);import_react160.useEffect(()=>{if(n<=0){p.onFire();return}let t2=setTimeout(()=>setN((v2)=>v2-1),1000);return()=>clearTimeout(t2)},[n,p.onFire]),useKeyboard(()=>p.onCancel());let bar3="\u2588".repeat(n)+"\u2591".repeat(Math.max(0,p.seconds-n));return $jsxs("box",{flexDirection:"column",width:58,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.warning,children:$jsx("strong",{children:p.title})})}),$jsx("box",{height:1}),$jsx("box",{minHeight:1,children:$jsx("text",{wrapMode:"word",children:p.body})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsxs("text",{fg:theme.warning,children:[bar3," ",n,"s"]})}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:p.action})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"press any key to cancel"})})]})};function openCountdown(dialog,opts){return new Promise((resolve4)=>{dialog.replace($jsx(Countdown,{...opts,onFire:()=>{dialog.clear(),resolve4(!0)},onCancel:()=>{dialog.clear(),resolve4(!1)}}),()=>resolve4(!1))})}var SECONDS=10,SUSPEND=process.platform==="darwin"?"pmset sleepnow":"systemctl suspend",run=(cmd)=>Bun.spawn(["sh","-c",cmd],{stdout:"ignore",stderr:"ignore"}),fired=new Map;function makeGoalHook(dialog,toast){let act=(goal,done2,total)=>{let pref=(exports_preferences.get("onGoalDone")??"toast").trim(),head=goal.length>60?goal.slice(0,57)+"\u2026":goal,n=total&&total>0?` ${done2}/${total} items`:"";if(toast.show({variant:"success",title:"Goal complete",message:head+n,duration:8000}),pref==="toast")return;let cmd=pref==="suspend"?SUSPEND:pref;openCountdown(dialog,{title:"Goal complete \u2014 "+(pref==="suspend"?"suspending":"running hook"),body:head,action:`\u2192 ${cmd}`,seconds:SECONDS}).then((ok)=>{if(ok)run(cmd)})};return{check:(sid2)=>{if(!sid2)return;io.goalState(sid2).then((s)=>{if(!s||s.status!=="done")return;if(fired.get(sid2)===s.goal)return;fired.set(sid2,s.goal);let list3=s.checklist??[],done2=list3.filter((i)=>i.status==="completed"||i.status==="impossible").length;act(s.goal,done2,list3.length)}).catch(()=>{})}}}var import_react162=__toESM(require_react_production(),1);function useVoice(gw,sys){let[enabled3,setEnabled]=import_react162.useState(!1),[recording,setRecording]=import_react162.useState(!1),[processing,setProcessing]=import_react162.useState(!1),[recordKeyRaw,setRecordKeyRaw]=import_react162.useState(),[tts,setTts]=import_react162.useState(!1),[onTranscript,setTranscript]=import_react162.useState(null),pending3=import_react162.useRef(0),recordGen=import_react162.useRef(0),toggleGen=import_react162.useRef(0),setOnTranscript=import_react162.useCallback((fn)=>setTranscript(fn?()=>fn:null),[]),reset4=import_react162.useCallback(()=>{toggleGen.current++,recordGen.current++,pending3.current=0,setEnabled(!1),setRecording(!1),setProcessing(!1),setTts(!1)},[]),recordKey=import_react162.useMemo(()=>parseVoiceRecordKey(recordKeyRaw),[recordKeyRaw]),keyLabel=import_react162.useMemo(()=>formatVoiceRecordKey(recordKey),[recordKey]),state3=import_react162.useMemo(()=>({enabled:enabled3,recording,processing,recordKey,tts}),[enabled3,recording,processing,recordKey,tts]),toggle=import_react162.useCallback(async(action,sid2)=>{let current2=++toggleGen.current;try{let r=await gw("voice.toggle",{action,session_id:sid2});if(toggleGen.current!==current2)return;if(r.enabled!==void 0){if(setEnabled(r.enabled),!r.enabled)recordGen.current++,setRecording(!1),setProcessing(!1)}if(r.tts!==void 0)setTts(r.tts);if(r.record_key)setRecordKeyRaw(r.record_key);let label3=formatVoiceRecordKey(parseVoiceRecordKey(r.record_key)),ttsMsg=r.tts?" \xB7 tts on":"",details2=action==="status"&&r.details?.trim()?` \xB7 ${r.details.trim()}`:"";sys(`voice ${r.enabled?"on":"off"}${ttsMsg} [${label3}]${details2}`)}catch(e){if(toggleGen.current!==current2)return;sys(`voice: ${e instanceof Error?e.message:"gateway error"}`)}},[gw,sys]),record2=import_react162.useCallback(async(sid2)=>{if(!enabled3){sys("voice: mode is off \u2014 enable with /voice on");return}if(pending3.current)return;let current2=++recordGen.current;pending3.current=current2;let starting=!recording,action=starting?"start":"stop";if(starting)setRecording(!0);else setRecording(!1),setProcessing(!1);try{let r=await gw("voice.record",{action,session_id:sid2});if(recordGen.current!==current2)return;if(starting&&r.status!=="recording"){if(setRecording(!1),r.status==="busy")setProcessing(!0),sys("voice: still transcribing; try again shortly")}}catch(e){if(recordGen.current!==current2)return;setRecording(!starting),sys(`voice error: ${e instanceof Error?e.message:"gateway error"}`)}finally{if(pending3.current===current2)pending3.current=0}},[enabled3,recording,gw,sys]);return{state:state3,toggle,record:record2,setEnabled,setRecording,setProcessing,setRecordKey:setRecordKeyRaw,reset:reset4,keyLabel,onTranscript,setOnTranscript}}function VoiceIndicator({voice,keyLabel}){let theme=useTheme().theme;if(!voice.enabled&&!voice.recording&&!voice.processing)return null;let text5,fg2=theme.text;if(voice.recording)text5="\u25CF recording",fg2=theme.error;else if(voice.processing)text5="\u25CC transcribing",fg2=theme.warning;else text5=`voice ready [${keyLabel}]`,fg2=theme.textMuted;return $jsx("text",{children:$jsxs("span",{fg:fg2,children:[text5," "]})})}function sessionCapabilities(input){let sessionConnected=Boolean(input.sid),metadataHydrated=input.ready;return{sessionConnected,metadataHydrated,canSubmitPrompt:sessionConnected,canDispatchGatewayCommand:sessionConnected,canDrainQueue:sessionConnected&&!input.streaming}}var import_react163=__toESM(require_react_production(),1);function openMessage(dialog,m2,ops){let text5=m2.parts.filter((p)=>p.type==="text").map((p)=>p.content).join("");dialog.replace($jsx(DialogSelect,{title:"Message Actions",options:[{title:"Copy",value:"copy",description:"message text to clipboard"},{title:"Rewind here",value:"rewind",description:"undo back to this turn (destructive)"},{title:"Fork here",value:"fork",description:"branch a new session at this point"}],onSelect:(o)=>{if(dialog.clear(),o.value==="copy")return void copyText(text5,ops.toast);if(o.value==="rewind")return ops.rewind(m2);if(o.value==="fork")return ops.fork(m2)}}))}async function undo(gw,count4,sid2){for(let i=0;i<count4;i++)await gw.request("session.undo",sid2?{session_id:sid2}:{})}var textOf=(message2)=>message2.parts.filter((part)=>part.type==="text").map((part)=>part.content).join("");function useMessageActions(args){let turns=import_react163.useCallback((message2)=>{let messages=args.turn.current.messages,at=messages.findIndex((item)=>item.id===message2.id);return at<0?0:messages.slice(at).filter((item)=>item.role==="user").length},[args.turn]),rewind=import_react163.useCallback(async(message2)=>{if(args.turn.current.streaming)return!1;let count4=turns(message2);if(!count4)return!1;try{await undo(args.gw,count4);let result=await args.gw.request("session.history");return args.dispatch({kind:"load",messages:transcriptToMessages(result.messages??[])}),args.composer.current?.set(textOf(message2)),args.focus("input"),!0}catch(err){return args.toast.show({variant:"error",message:err instanceof Error?err.message:String(err)}),!1}},[args.gw,args.toast,args.turn,args.dispatch,args.composer,args.focus,turns]),fork2=import_react163.useCallback(async(message2)=>{if(args.turn.current.streaming)return;let result=await args.gw.request("session.branch",{}).catch((err)=>{return args.toast.show({variant:"error",message:`branch failed: ${err.message}`}),null});if(!result?.session_id)return;try{if(await undo(args.gw,turns(message2),result.session_id),!await args.activate(result.session_id)){await args.session.close(result.session_id);return}args.composer.current?.set(textOf(message2)),args.focus("input"),args.toast.show({variant:"success",message:`forked \u2192 ${result.title??result.session_id}`})}catch(err){await args.session.close(result.session_id),args.toast.show({variant:"error",message:err instanceof Error?err.message:String(err)})}},[args.gw,args.toast,args.turn,args.activate,args.session,args.composer,args.focus,turns]),menu=import_react163.useCallback((message2)=>{if(args.turn.current.streaming)return;openMessage(args.dialog,message2,{rewind,fork:fork2,toast:args.toast})},[args.dialog,args.toast,args.turn,rewind,fork2]);return{rewind,fork:fork2,menu}}var BUSY_RE=/session busy|waiting for model response/i,App=(props)=>$jsx(ThemeProvider,{initial:props.initialTheme,children:$jsx(GatewayProvider,{client:props.gateway,children:$jsx(ToastProvider,{children:$jsx(KeysProvider,{overrides:props.keyOverrides,children:$jsx(DialogProvider,{children:$jsx(CommandProvider,{children:$jsx(PluginProvider,{plugins:props.plugins,children:$jsx(BackgroundProvider,{children:$jsx(AppInner,{launch:props.launch??{mode:"new"}})})})})})})})})}),AppInner=({launch:launch0})=>{let gw=useGateway(),gwRestart=useGatewayRestart(),dialog=useDialog(),dialogOpen=useDialogOpen(),themeCtx=useTheme(),toast=useToast(),renderer=useRenderer(),plugins=usePlugins(),session=useSession(),dims=useTerminalDimensions(),goalHook=import_react165.useMemo(()=>makeGoalHook(dialog,toast),[dialog,toast]),[turn,dispatch]=import_react165.useReducer(turnReducer,initialTurn),[ready,setReady]=import_react165.useState(!1),[sid2,setSid]=import_react165.useState(""),sidRef=import_react165.useRef(sid2);sidRef.current=sid2;let[starting,setStarting]=import_react165.useState(!1),startRef=import_react165.useRef(starting);startRef.current=starting;let active=turn.streaming||starting,capabilities=sessionCapabilities({sid:sid2,ready,streaming:active}),[tab,setTab]=import_react165.useState(CHAT_TAB),[subTabs,setSubTabs]=import_react165.useState(()=>({[SESSIONS_TAB]:0,[AUTOMATION_TAB]:0,[CONFIG_TAB]:0,[EIKON_TAB]:0})),setSub=import_react165.useCallback((tabIdx,sub2)=>setSubTabs((prev)=>prev[tabIdx]===sub2?prev:{...prev,[tabIdx]:sub2}),[]),sessSub=import_react165.useCallback((i)=>setSub(SESSIONS_TAB,i),[setSub]),autoSub=import_react165.useCallback((i)=>setSub(AUTOMATION_TAB,i),[setSub]),cfgSub=import_react165.useCallback((i)=>setSub(CONFIG_TAB,i),[setSub]),eikSub=import_react165.useCallback((i)=>setSub(EIKON_TAB,i),[setSub]),[hideSidebar,setHideSidebar]=import_react165.useState(!1),[usage,setUsage]=import_react165.useState(void 0),[info3,setInfo]=import_react165.useState(null),[title,setTitle]=import_react165.useState(""),caption=title.trim(),titleRef=import_react165.useRef(caption);titleRef.current=caption,import_react165.useEffect(()=>{process.removeAllListeners("SIGINT"),process.on("SIGINT",()=>quit(renderer,sidRef.current,titleRef.current,gw))},[renderer,gw]),import_react165.useEffect(()=>{let w2=warning();if(!w2)return;toast.show({variant:"warning",title:"control server exposed",message:w2.message,duration:15000})},[toast]);let[focusRegion,setFocusRegion]=import_react165.useState("input"),goToTab=import_react165.useCallback((t2)=>{setTab(t2),setFocusRegion(t2===CHAT_TAB?"input":"content")},[]),goTo=import_react165.useCallback((t2,sub2)=>{setTab(t2),setSubTabs((prev)=>prev[t2]===sub2?prev:{...prev,[t2]:sub2}),setFocusRegion(t2===CHAT_TAB?"input":"content")},[]),[status2,setStatus]=import_react165.useState(""),[escHint,setEscHint]=import_react165.useState(!1),[eikon,setEikon]=import_react165.useState(void 0),[queue,setQueue]=import_react165.useState([]),[busy2,setBusy]=import_react165.useState("queue"),turnRef=import_react165.useRef(turn);turnRef.current=turn;let queueRef=import_react165.useRef(queue);queueRef.current=queue;let launchRef=import_react165.useRef(launch0),launch=launchRef.current,[splash,setSplash]=import_react165.useState(launch.splash!==!1),[switching,setSwitching]=import_react165.useState(!1),summoned=import_react165.useRef(!1),creating=import_react165.useRef(!1),[composing,setComposing]=import_react165.useState(!1),splashLast=import_react165.useMemo(()=>launch.mode==="new"?lastReal():void 0,[launch.mode]),splashInfo=import_react165.useMemo(()=>info3?{agentVersion:info3.version,behind:info3.update_behind,model:info3.model}:void 0,[info3?.version,info3?.update_behind,info3?.model]),splashLastProp=import_react165.useMemo(()=>splashLast?{id:splashLast.id,title:splashLast.title}:void 0,[splashLast]),news=import_react165.useMemo(()=>readChangelog()?.headline,[]),[attachments,setAttachments]=import_react165.useState([]),attachmentsRef=import_react165.useRef(attachments);attachmentsRef.current=attachments;let[cloudH,setCloudH]=import_react165.useState(CLOUD_MIN),[pick2,setPick]=import_react165.useState(void 0),[skin2,setSkin]=import_react165.useState(()=>deriveSkin(void 0)),inflight=import_react165.useRef(!1),hold=import_react165.useRef(!1),pending3=import_react165.useRef(!1),detaching=import_react165.useRef(0),[pulse,setPulse]=import_react165.useState(0),start2=import_react165.useCallback(()=>{inflight.current=!1,pending3.current=!1,setPulse((n)=>n+1)},[]),settle=import_react165.useCallback(()=>{if(!hold.current)return;hold.current=!1,setPulse((n)=>n+1)},[]),undone=import_react165.useRef([]),sessionStart=import_react165.useRef(Date.now()),composer2=import_react165.useRef(null),promptRef=import_react165.useRef(null),{cmds}=useSlashCommands(),cmdsRef=import_react165.useRef(cmds);cmdsRef.current=cmds;let sys=import_react165.useCallback((text5)=>dispatch({kind:"system",text:text5}),[]),voice=useVoice(gw.request.bind(gw),sys);import_react165.useEffect(()=>{voice.setOnTranscript((text5)=>{let c=composer2.current;if(!c)return;c.set(""),setTimeout(()=>sendRef.current(text5),0)})},[]),useTerminalTitle(active,info3?.cwd);let[errorPulse,setErrorPulse]=import_react165.useState(!1);import_react165.useEffect(()=>{let restart=(mode2="resume")=>{let sid3=sidRef.current;if(mode2==="resume"&&sid3)launchRef.current={mode:"resume",sid:sid3,splash:!1};gw.setSession(""),setReady(!1),setStarting(!1),setStatus("gateway restarting"),voice.reset()},exit=(code2)=>{let text5=`gateway exited${code2===null?"":` (${code2})`}`,sid3=sidRef.current;if(sid3)launchRef.current={mode:"resume",sid:sid3,splash:!1};gw.setSession(""),setReady(!1),setStarting(!1),setStatus(text5),setErrorPulse(!0),voice.reset(),dispatch({kind:"system",text:text5})};return gw.on("restart",restart),gw.on("exit",exit),()=>{gw.off("restart",restart),gw.off("exit",exit)}},[gw]);let agentState=errorPulse?"error":turn.toolActive?"working":turn.streaming&&turn.hasContent?"speaking":active?"thinking":composing?"listening":"idle",onAvatarHold=import_react165.useCallback((s)=>{if(s==="error")setErrorPulse(!1)},[]),prompt=import_react165.useMemo(()=>pending2(turn.messages),[turn.messages]),cloudAuto=turn.streaming&&!turn.hasContent&&!prompt,[force,setForce]=import_react165.useState(void 0),cloud=!prompt&&(force??cloudAuto),prevStream=import_react165.useRef(turn.streaming);import_react165.useEffect(()=>{if(!prevStream.current&&turn.streaming)setForce(void 0),setPick(void 0);prevStream.current=turn.streaming},[turn.streaming]);let onPick=import_react165.useCallback((m2)=>{setPick((p)=>{if(m2&&p&&m2.id===p.id){setForce(!1);return}return setForce(!!m2),m2})},[]),onAvatar=import_react165.useCallback(()=>{let next2=!cloud;if(!next2)setPick(void 0);setForce(next2)},[cloud]),closeCloud=import_react165.useCallback(()=>{setForce(!1),setPick(void 0)},[]),intr=import_react165.useRef(()=>{}),steer=import_react165.useCallback((text5)=>{let v2=text5.trim();if(!v2)return;gw.request("session.steer",{text:v2}).then((r)=>toast.show(r.status==="queued"?{variant:"success",message:"Queued \u2014 lands on next tool result"}:{variant:"info",message:"No turn running; send as a normal message"})).catch((e)=>toast.show({variant:"error",message:e.message}))},[gw,toast]),openSteer=import_react165.useCallback(()=>{openTextPrompt(dialog,{title:"Steer active turn",label:"Soft nudge for the running session"}).then((v2)=>{if(v2)steer(v2)})},[dialog,steer]),onEnqueue=import_react165.useCallback((t2)=>{if(busy2==="steer"){let v2=t2.trim();if(!v2)return;gw.request("session.steer",{text:v2}).then((r)=>{if(r.status==="queued")return toast.show({variant:"success",message:"Queued \u2014 lands on next tool result"});setQueue((q5)=>[...q5,t2]),toast.show({variant:"info",message:"steer rejected \u2014 queued for next turn"})}).catch(()=>setQueue((q5)=>[...q5,t2]));return}if(busy2==="interrupt"){hold.current=!0,setQueue((q5)=>[t2,...q5]),intr.current();return}setQueue((q5)=>[...q5,t2])},[busy2,gw,toast]),updateAttachments=import_react165.useCallback((next2)=>{let value2=typeof next2==="function"?next2(attachmentsRef.current):next2;attachmentsRef.current=value2,setAttachments(value2)},[]),onAttach=import_react165.useCallback((r)=>updateAttachments((a)=>[...a,r]),[updateAttachments]),stream=useStream({dispatch,session,launchRef,sidRef,sessionStart,goalHook,setSid,setInfo,setReady,setTitle,setBusy,setStarting,setUsage,setStatus,setSkin,setErrorPulse,settle,onVoiceStatus:(state3)=>{voice.setRecording(state3==="listening"||state3==="recording"),voice.setProcessing(state3==="transcribing"||state3==="processing")},onVoiceTranscript:(text5,noSpeechLimit)=>{if(voice.setRecording(!1),voice.setProcessing(!1),noSpeechLimit){voice.setEnabled(!1),sys("voice: disabled after repeated silence");return}voice.onTranscript?.(text5)},start:start2}),interrupt=import_react165.useCallback(()=>{if(startRef.current&&!turnRef.current.streaming)hold.current=!0;stream.doInterrupt()},[stream.doInterrupt]);intr.current=interrupt;let reset4=import_react165.useCallback(()=>{stream.interrupted.current=!1,hold.current=!1,pending3.current=!1,toast.clear("credits.depleted"),undone.current=[],dispatch({kind:"reset"}),setUsage(void 0),setReady(!1),setStarting(!1),setStatus(""),setTitle(""),updateAttachments([])},[toast,updateAttachments]),newSession=import_react165.useCallback(async()=>{if(creating.current)return;creating.current=!0,setSwitching(!0);let prev=sidRef.current;summoned.current=!0,setSplash(!0),setReady(!1),gw.setSession("");try{let r=await session.create();if(reset4(),setSid(r.id),r.info)setInfo(r.info),setUsage(r.info.usage);if(setReady(!0),setStarting(!1),setStatus(""),sessionStart.current=Date.now(),prev)session.close(prev,{preserveBackground:!0})}catch(err){if(prev)gw.setSession(prev),setReady(!0);setSplash(!1),summoned.current=!1,dispatch({kind:"system",text:`Failed to create session: ${err instanceof Error?err.message:String(err)}`})}finally{creating.current=!1,setSwitching(!1)}},[reset4,session,gw]),switchSession=import_react165.useCallback(async(target2)=>{let prev=sidRef.current;summoned.current=!0,setSplash(!0),setSwitching(!0),gw.setSession(""),setSid(""),goToTab(CHAT_TAB);try{let res=await session.resume(target2);if(reset4(),setSid(res.id),res.info)setInfo(res.info),setUsage(res.info.usage);if(setReady(!0),sessionStart.current=Date.now(),res.messages.length)dispatch({kind:"load",messages:res.messages});if(prev&&prev!==res.id)session.close(prev,{preserveBackground:!0});setSplash(!1),summoned.current=!1}catch(err){if(prev)gw.setSession(prev),setSid(prev),setReady(!0);dispatch({kind:"system",text:`Failed to resume: ${err instanceof Error?err.message:String(err)}`}),setSplash(!1),summoned.current=!1}finally{setSwitching(!1)}},[reset4,session,goToTab,gw]),liveStatus=(state3,running2=!1)=>{if(state3==="waiting")return"waiting for input\u2026";if(state3==="starting")return"starting agent\u2026";return running2||state3==="working"?"running\u2026":"ready"},activateSession=import_react165.useCallback(async(target2)=>{let prev=sidRef.current;summoned.current=!0,setSplash(!0),setSwitching(!0),gw.setSession(""),setSid(""),goToTab(CHAT_TAB);try{let res=await session.activate(target2);if(reset4(),setSid(res.id),res.info)setInfo(res.info),setUsage(res.info.usage);if(sessionStart.current=res.startedAt??Date.now(),dispatch({kind:"load.live",messages:res.messages,streaming:res.running}),setStatus(liveStatus(res.status,res.running)),setReady(!0),setSplash(!1),summoned.current=!1,prev&&prev!==res.id)toast.show({variant:"info",message:"switched live session"});return!0}catch(err){if(prev)gw.setSession(prev),setSid(prev),setReady(!0);return dispatch({kind:"system",text:`Failed to activate: ${err instanceof Error?err.message:String(err)}`}),setSplash(!1),summoned.current=!1,!1}finally{setSwitching(!1)}},[reset4,session,goToTab,toast,gw]),switchProfile=import_react165.useCallback((newHome,name)=>{voice.reset(),rehome(newHome),reset4(),gw.setSession(""),setSid(""),setInfo(null),setSkin(deriveSkin(void 0)),summoned.current=!0,setSplash(!0),launchRef.current={mode:"new",splash:!0},toast.show({variant:"info",message:`Switching to '${name}'\u2026`}),goToTab(CHAT_TAB),gwRestart("new")},[reset4,goToTab,gwRestart,toast,gw]),loadEikon=import_react165.useCallback((path4)=>{try{setEikon(parseEikonFile(path4))}catch{setEikon(void 0)}},[]),eikonName=usePref("eikon"),eikonRev=import_react165.useSyncExternalStore(exports_eikon.onRevision,exports_eikon.revision);import_react165.useEffect(()=>{let p=eikonName&&exports_eikon.baked(eikonName)||bundledEikonPath(skin2.skin?.name);if(p)loadEikon(p);else setEikon(void 0)},[eikonName,eikonRev,skin2.skin?.name,loadEikon]);let messageActions=useMessageActions({gw,dialog,toast,session,activate:activateSession,composer:composer2,turn:turnRef,dispatch,focus:setFocusRegion}),rewind=messageActions.rewind,msgMenu=messageActions.menu,attachClipboard=import_react165.useCallback(()=>{gw.request("clipboard.paste").then((r)=>r.attached?updateAttachments((a)=>[...a,r]):toast.show({variant:"info",message:r.message??"No image in clipboard"})).catch((e)=>toast.show({variant:"error",message:e.message}))},[gw,toast,updateAttachments]),sendRef=import_react165.useRef(()=>{}),slash3=useSlash({dispatch,session,turnRef,queueRef,sendRef,composer:composer2,summoned,undone,capabilities,info:info3,sid:sid2,title:caption,skin:skin2,setQueue,setFocusRegion,setSplash,setAttachments:updateAttachments,setInfo,setUsage,setTitle,newSession,switchSession,activateSession,rewind,goTo,attachClipboard,voiceToggle:voice.toggle}),send=import_react165.useCallback(async(raw2)=>{if(creating.current)return;if(["exit","quit",":q",":q!",":wq"].includes(raw2.trim()))return quit(renderer,sidRef.current,titleRef.current,gw);if(detaching.current>0){if(raw2.trim())composer2.current?.set(raw2);setStatus("detaching image\u2026");return}let m2=raw2.match(/^\/(\S+)(?:\s+([\s\S]*))?$/);if(m2){let[,name,arg=""]=m2,r=resolve9(cmdsRef.current,name);if("hit"in r)return slash3(r.hit,arg.trim());if("ambiguous"in r){let head=r.ambiguous.slice(0,6).join(", ");return dispatch({kind:"system",text:`ambiguous: /${name} \u2192 ${head}${r.ambiguous.length>6?", \u2026":""}`})}}let text5=raw2;if(hasInterp(raw2))setStatus("interpolating\u2026"),text5=await interpolate(gw,raw2),setStatus("");stream.interrupted.current=!1;let att=attachmentsRef.current,withMedia=att.length?[...att.flatMap((a)=>a.path?[`MEDIA:${a.path}`]:[]),text5].filter(Boolean).join(`
|
|
4211
|
+
`):text5;if(pending3.current){setQueue((q5)=>[...q5,raw2]),setStatus("queued for next turn");return}pending3.current=!0,setPulse((n)=>n+1),gw.request("prompt.submit",{text:text5}).then((r)=>{if(dispatch({kind:"user",text:withMedia}),r.status==="streaming"&&!turnRef.current.streaming)setStarting(!0),setStatus("starting agent\u2026");updateAttachments([]),undone.current=[],setTab(CHAT_TAB)}).catch((e)=>{let msg=e instanceof Error?e.message:String(e);if(BUSY_RE.test(msg)){pending3.current=!1,setPulse((n)=>n+1),inflight.current=!0,setQueue((q5)=>[text5,...q5]),setStatus("queued for next turn"),toast.show({variant:"info",message:"queued for next turn"}),setTimeout(()=>{inflight.current=!1,setPulse((n)=>n+1)},400);return}pending3.current=!1,setPulse((n)=>n+1),inflight.current=!1,setStarting(!1),dispatch({kind:"system",text:`submit failed: ${msg}`}),toast.show({variant:"error",message:msg})})},[gw,slash3,toast,updateAttachments]);sendRef.current=send;let onShell=import_react165.useCallback((command)=>{setSplash(!1),dispatch({kind:"system",text:`$ ${command}`}),setStatus("running\u2026"),gw.request("shell.exec",{command}).then((r)=>{let out=(r.stdout??"").trimEnd(),err=(r.stderr??"").trimEnd(),body2=[out,err&&`stderr:
|
|
4212
4212
|
${err}`].filter(Boolean).join(`
|
|
4213
|
-
`);if(dispatch({kind:"system",text:body2||`(exit ${r.code??0})`}),(r.code??0)!==0)toast.show({variant:"warning",message:`exit ${r.code}`})}).catch((e)=>dispatch({kind:"system",text:`error: ${e.message}`})).finally(()=>setStatus(""))},[gw,toast]),onSend=
|
|
4213
|
+
`);if(dispatch({kind:"system",text:body2||`(exit ${r.code??0})`}),(r.code??0)!==0)toast.show({variant:"warning",message:`exit ${r.code}`})}).catch((e)=>dispatch({kind:"system",text:`error: ${e.message}`})).finally(()=>setStatus(""))},[gw,toast]),onSend=import_react165.useCallback((raw2)=>{return setSplash(!1),send(raw2)},[send]),onEmptyEnter=import_react165.useCallback(()=>{if(!splash||summoned.current||!splashLast||composing)return!1;return setSplash(!1),switchSession(splashLast.id),!0},[splash,splashLast,composing,switchSession]);import_react165.useEffect(()=>{if(turn.streaming)start2()},[turn.streaming,start2]),import_react165.useEffect(()=>{if(!capabilities.canDrainQueue||inflight.current||hold.current||pending3.current||queue.length===0)return;let[head,...rest]=queue;inflight.current=!0,setQueue(rest),send(head)},[capabilities.canDrainQueue,queue,send,pulse]);let dequeue=import_react165.useCallback((i)=>{let item=queueRef.current[i];if(item===void 0)return;setQueue((q5)=>q5.filter((_2,j2)=>j2!==i)),composer2.current?.set(item),setFocusRegion("input")},[]),extra=plugins.routes,all2=import_react165.useMemo(()=>[...TABS,...extra.map((r)=>({name:r.name,description:r.description??"Plugin"}))],[extra]),routeName=import_react165.useRef(void 0),routesRef=import_react165.useRef(extra),tabMax=all2.length-1;import_react165.useEffect(()=>{plugins.bind(goTo,()=>all2[tab]?.name)},[plugins,goTo,all2,tab]),import_react165.useEffect(()=>{let changed2=routesRef.current!==extra;if(routesRef.current=extra,changed2&&tab>=TABS.length){let next2=extra.findIndex((route2)=>route2.name===routeName.current);if(next2<0){goToTab(CHAT_TAB);return}let index4=TABS.length+next2;if(index4!==tab){goToTab(index4);return}}routeName.current=all2[tab]?.name},[extra,all2,tab,goToTab]);let subCount=SUB_TABS[tab]?.length??0,cycleSub=import_react165.useCallback((dir2)=>{let labels=SUB_TABS[tab];if(!labels||labels.length===0)return;setSubTabs((prev)=>{let cur=prev[tab]??0,next2=(cur+dir2+labels.length)%labels.length;return next2===cur?prev:{...prev,[tab]:next2}})},[tab]);useAppKeys({tab,tabMax,chatTab:CHAT_TAB,setTab,subCount,cycleSub,focusRegion,setFocusRegion,streaming:turn.streaming,starting,dialogOpen:dialog.open,composer:composer2,onPromptKey:(k2)=>promptRef.current?.feed(k2)??!1,onEscape:()=>{if(!splash||!summoned.current)return!1;return setSplash(!1),summoned.current=!1,!0},onInterrupt:interrupt,queued:queue.length,onFlushQueue:()=>{hold.current=!0,interrupt()},onQuit:()=>quit(renderer,sid2,caption,gw),onQuitArm:(label3)=>toast.show({variant:"info",message:`${label3} again to quit`}),onInterruptNotice:()=>{setEscHint(!0),setTimeout(()=>setEscHint(!1),5000)},onCopyLast:()=>{let m2=[...turnRef.current.messages].reverse().find((x2)=>x2.role==="assistant"&&text2(x2));if(m2)copyText(text2(m2),toast)},onCopyToast:toast.show,onAttachClipboard:attachClipboard,onDetachLast:()=>{if(detaching.current>0)return setStatus("detaching image\u2026"),!0;let target2=attachmentsRef.current.at(-1);if(!target2?.path)return!1;return detaching.current+=1,setStatus("detaching image\u2026"),setPulse((n)=>n+1),gw.request("image.detach",{path:target2.path}).then(()=>updateAttachments((a)=>a.filter((x2)=>x2.path!==target2.path))).catch((e)=>toast.show({variant:"error",message:e.message})).finally(()=>{detaching.current=Math.max(0,detaching.current-1),setStatus(""),setPulse((n)=>n+1)}),!0},onNotice:(text5)=>dispatch({kind:"system",text:text5}),onToggleSidebar:()=>setHideSidebar((v2)=>!v2),onSteer:openSteer,onStash:()=>{let c=composer2.current,v2=c?.value().trim()??"";if(!v2){let e=exports_stash.pop();if(!e)return toast.show({variant:"info",message:"stash empty"});c?.set(e.text);return}let n=exports_stash.push(v2);c?.set(""),toast.show({variant:"info",message:`stashed (${n})`})},voiceRecordKey:voice.state.recordKey,voiceEnabled:voice.state.enabled,onVoiceRecord:()=>voice.record(sidRef.current)}),useBridge({tab,ready,streaming:active,messages:turn.messages,sid:sid2,focusRegion,setTab,setFocusRegion,dispatch,composer:composer2});let contentFocused=focusRegion==="content"&&!active&&!dialogOpen,promptAnswer=import_react165.useCallback((id,label3,ok)=>dispatch({kind:"prompt.answered",id,label:label3,ok}),[]),promptWire=import_react165.useMemo(()=>({ref:promptRef,onAnswer:promptAnswer}),[promptAnswer]);import_react165.useEffect(()=>{if(prompt&&tab!==CHAT_TAB)setTab(CHAT_TAB)},[prompt?.id]);let content=()=>{let inner=(()=>{switch(tab){case CHAT_TAB:return $jsx(Chat,{messages:turn.messages,streaming:turn.streaming,prompt:promptWire,cloud,cloudH,pick:pick2,onResize:setCloudH,onPick,onClose:closeCloud,onRewind:msgMenu});case SESSIONS_TAB:return $jsx(SessionsGroup,{focused:contentFocused,sub:subTabs[SESSIONS_TAB]??0,setSub:sessSub,onSwitch:switchSession,onActivateLive:activateSession,currentId:sid2,messages:turn.messages,sessionStart:sessionStart.current,info:info3??void 0,usage});case AUTOMATION_TAB:return $jsx(Automation,{focused:contentFocused,sub:subTabs[AUTOMATION_TAB]??0,setSub:autoSub,sessionId:sid2,onSwitchProfile:switchProfile});case CONFIG_TAB:return $jsx(ConfigGroup,{focused:contentFocused,sub:subTabs[CONFIG_TAB]??0,setSub:cfgSub});case EIKON_TAB:return $jsx(EikonGroup,{focused:contentFocused,sub:subTabs[EIKON_TAB]??0,setSub:eikSub});default:{let r=extra[tab-TABS.length];return r?r.render({focused:contentFocused}):null}}})(),name=all2[tab]?.name??"unknown";return $jsx(import_react165.Profiler,{id:`tab:${name}`,onRender,children:inner})},theme=themeCtx.theme,onMouseUp=import_react165.useCallback(()=>copySelection(renderer,toast),[renderer,toast]),inputFocused=focusRegion==="input"&&!prompt&&!dialogOpen,sidebarVisible=dims.width>=(tab===CHAT_TAB?120:140)&&!hideSidebar,branch2=useGitBranch(info3?.cwd),hidden3=!sidebarVisible?hidden2({info:info3,usage,profile:activeProfileName(),title:caption,branch:branch2}):void 0;return $jsx(import_react165.Profiler,{id:"shell",onRender,children:$jsx(SkinProvider,{value:skin2,children:$jsxs("box",{width:"100%",height:"100%",flexDirection:"column",backgroundColor:theme.background,onMouseUp,children:[$jsx(TabBar,{tabs:all2,activeTab:tab,onTabChange:goToTab}),$jsxs("box",{flexGrow:1,flexDirection:"row",children:[$jsxs("box",{flexGrow:1,flexDirection:"column",children:[$jsxs("box",{flexGrow:1,position:"relative",children:[content(),splash&&tab===CHAT_TAB?$jsx(Splash,{info:splashInfo,last:summoned.current?void 0:splashLastProp,composing,news,loading:switching||!info3}):null]}),$jsxs("box",{flexShrink:0,zIndex:1,children:[$jsx(VoiceIndicator,{voice:voice.state,keyLabel:voice.keyLabel}),$jsx(Composer,{ref:composer2,focused:inputFocused,canSubmitPrompt:capabilities.canSubmitPrompt&&detaching.current===0,ready,streaming:active||pending3.current,starting,status:status2,model:info3?.model,subagents:usage?.active_subagents??info3?.usage?.active_subagents,hidden:hidden3,escHint,queue,attachments,cmds,onSend,onSlash:slash3,onShell,onAttach,onAttachClipboard:attachClipboard,onEnqueue,onDequeue:dequeue,onDirty:setComposing,onEmptyEnter})]})]}),sidebarVisible?$jsx(import_react165.Profiler,{id:"sidebar",onRender,children:$jsx(Sidebar,{agentState,info:info3,usage,eikon,profile:activeProfileName(),title:caption,cloud:tab===0&&cloud,pulse:active,onAvatar,onAvatarHold})}):null]}),plugins.has("app_bottom")?$jsx("box",{height:1,flexShrink:0,paddingX:1,overflow:"hidden",children:$jsx(plugins.Slot,{name:"app_bottom",mode:"single_winner",sid:sid2,tab,streaming:active})}):null]})})})};var EIKON_CLI_USAGE=`herm eikon \u2014 install and manage Herm avatars
|
|
4214
4214
|
|
|
4215
4215
|
Usage:
|
|
4216
4216
|
herm eikon search [query] [--json]
|