@automagik/genie 4.260329.20 → 4.260329.22
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/.claude-plugin/marketplace.json +1 -1
- package/dist/genie.js +7 -10
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/plugins/genie/.claude-plugin/plugin.json +1 -1
- package/plugins/genie/package.json +1 -1
- package/src/hooks/handlers/orchestration-guard.ts +3 -4
- package/src/hooks/index.ts +12 -4
- package/src/hooks/types.ts +2 -0
- package/src/tui/app.tsx +4 -179
- package/src/tui/components/Nav.tsx +127 -197
- package/src/tui/components/TreeNode.tsx +48 -24
- package/src/tui/db.ts +2 -182
- package/src/tui/session-tree.ts +120 -0
- package/src/tui/tmux.ts +0 -35
- package/src/tui/tree.ts +1 -98
- package/src/tui/types.ts +2 -63
- package/src/tui/activity.ts +0 -108
- package/src/tui/components/ClaudeView.tsx +0 -223
- package/src/tui/components/TabBar.tsx +0 -56
- package/src/tui/components/TmuxView.tsx +0 -163
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "genie",
|
|
13
|
-
"version": "4.260329.
|
|
13
|
+
"version": "4.260329.22",
|
|
14
14
|
"source": "./plugins/genie",
|
|
15
15
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, wish them into plans, make with parallel agents, ship as one team. A coding genie that grows with your project."
|
|
16
16
|
}
|
package/dist/genie.js
CHANGED
|
@@ -1432,8 +1432,7 @@ ${answer}
|
|
|
1432
1432
|
ORDER BY seq
|
|
1433
1433
|
`).map((r)=>({id:r.id,seq:r.seq,title:r.title,stage:r.stage,repoPath:r.repo_path}))}function getRepoPathSafe(){try{return execSync12("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}var init_task_close_merged=()=>{};var palette,icons,tmuxStyle;var init_theme2=__esm(()=>{palette={purple:"#a855f7",violet:"#7c3aed",cyan:"#22d3ee",emerald:"#34d399",bg:"#1a1028",bgLight:"#241838",bgLighter:"#2e2048",text:"#e2e8f0",textDim:"#94a3b8",textMuted:"#64748b",border:"#414868",borderActive:"#7c3aed",scrollTrack:"#414868",scrollThumb:"#7aa2f7",active:"#22d3ee",success:"#34d399",warning:"#fbbf24",error:"#f87171",idle:"#94a3b8"},icons={org:"\u25C6",project:"\u25B8",projectOpen:"\u25BE",board:"\u2261",boardOpen:"\u2261",column:"\u2502",task:"\u25CB",taskActive:"\u25CF",taskDone:"\u2713",agent:"\u25B6",collapsed:"\u25B8",expanded:"\u25BE"},tmuxStyle={statusBg:"#1a1028",statusFg:"#e2e8f0",activeBorder:"#7c3aed",inactiveBorder:"#414868",activeTab:"#7c3aed",inactiveTab:"#414868"}});import{execSync as execSync13,spawnSync as spawnSync2}from"child_process";function hasTmux(){try{return execSync13("which tmux",{stdio:"ignore"}),!0}catch{return!1}}function isInsideTuiSession(){return process.env.GENIE_TUI_PANE==="left"}function createTuiSession(){let cols=process.stdout.columns||120,rows=process.stdout.rows||40;try{execSync13(`tmux kill-session -t ${SESSION_NAME} 2>/dev/null`,{stdio:"ignore"})}catch{}execSync13(`tmux new-session -d -s ${SESSION_NAME} -x ${cols} -y ${rows} -e GENIE_TUI_PANE=left`,{stdio:"ignore"}),execSync13(`tmux split-window -h -t ${SESSION_NAME}:0 -l ${cols-NAV_WIDTH-1}`,{stdio:"ignore"});let panes=execSync13(`tmux list-panes -t ${SESSION_NAME}:0 -F '#{pane_id}'`,{encoding:"utf-8"}).trim().split(`
|
|
1434
1434
|
`),leftPane=panes[0],rightPane=panes[1]||panes[0];return applyTmuxStyle(SESSION_NAME),setupKeybindings(SESSION_NAME),{session:SESSION_NAME,leftPane,rightPane}}function resolveRightPane(rightPane){try{return execSync13(`tmux display-message -t ${rightPane} -p ''`,{stdio:"ignore"}),rightPane}catch{try{let panes=execSync13(`tmux list-panes -t ${SESSION_NAME}:0 -F '#{pane_id}'`,{encoding:"utf-8"}).trim().split(`
|
|
1435
|
-
`);return panes[1]||panes[0]}catch{return rightPane}}}function ensureSession3(sessionName){try{execSync13(`tmux has-session -t '${sessionName}' 2>/dev/null`,{stdio:"ignore"})}catch{try{execSync13(`tmux new-session -d -s '${sessionName}'`,{stdio:"ignore"})}catch{}}}function attachProject(rightPane,targetSession){let pane=resolveRightPane(rightPane);ensureSession3(targetSession);try{execSync13(`tmux respawn-pane -k -t ${pane} "TMUX='' tmux attach-session -t '${targetSession}'"`,{stdio:"ignore"})}catch{}}function switchRightPane(rightPane,targetSession){attachProject(rightPane,targetSession)}function attachProjectWindow(rightPane,targetSession,windowIndex){let pane=resolveRightPane(rightPane);if(ensureSession3(targetSession),windowIndex!==void 0)try{execSync13(`tmux select-window -t '${targetSession}:${windowIndex}'`,{stdio:"ignore"})}catch{}try{execSync13(`tmux respawn-pane -k -t ${pane} "TMUX='' tmux attach-session -t '${targetSession}'"`,{stdio:"ignore"})}catch{}}function setupKeybindings(session){try{execSync13(`tmux bind-key -T ${KEY_TABLE} Tab select-pane -t ${session}:0.1 \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync13(`tmux bind-key -T ${KEY_TABLE} C-b if-shell "[ $(tmux display-message -p '#{pane_width}' -t ${session}:0.0) -gt 5 ]" "resize-pane -t ${session}:0.0 -x 0" "resize-pane -t ${session}:0.0 -x ${NAV_WIDTH}" \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync13(`tmux bind-key -T ${KEY_TABLE} C-t send-keys -t ${session}:0.1 C-b c \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync13(`tmux bind-key -T ${KEY_TABLE} 'C-\\' run-shell "tmux kill-session -t ${session}"`,{stdio:"ignore"}),execSync13(`tmux set-hook -t ${session} client-session-changed "switch-client -T ${KEY_TABLE}"`,{stdio:"ignore"}),execSync13(`tmux switch-client -T ${KEY_TABLE}`,{stdio:"ignore"})}catch{}}function applyTmuxStyle(session){try{let cmds=[`set-option -t ${session} pane-border-style 'fg=${tmuxStyle.inactiveBorder}'`,`set-option -t ${session} pane-active-border-style 'fg=${tmuxStyle.activeBorder}'`,`set-option -t ${session} status off`,`set-option -t ${session} mouse on`];for(let cmd of cmds)execSync13(`tmux ${cmd}`,{stdio:"ignore"})}catch{}}function cleanup(session=SESSION_NAME){try{execSync13(`tmux unbind-key -T ${KEY_TABLE} Tab 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux unbind-key -T ${KEY_TABLE} C-b 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux unbind-key -T ${KEY_TABLE} C-t 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux unbind-key -T ${KEY_TABLE} 'C-\\' 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux set-hook -u -t ${session} client-session-changed 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux kill-session -t ${session} 2>/dev/null`,{stdio:"ignore"})}catch{}}function attachTuiSession(){spawnSync2("tmux",["attach-session","-t",SESSION_NAME],{stdio:"inherit"})}function listSessionWindows(session){try{let output=execSync13(`tmux list-windows -t ${session} -F '#{window_name}:#{window_index}:#{?window_active,1,0}' 2>/dev/null`,{encoding:"utf-8"}).trim();if(!output)return[];return output.split(`
|
|
1436
|
-
`).map((line)=>{let[name,idx,active]=line.split(":");return{name,index:Number.parseInt(idx,10),active:active==="1"}})}catch{return[]}}var SESSION_NAME="genie-tui",KEY_TABLE="genie-tui",NAV_WIDTH=30;var init_tmux2=__esm(()=>{init_theme2()});var highlights_default="./highlights-ghv9g403.scm";var init_highlights=()=>{};var tree_sitter_javascript_default="./tree-sitter-javascript-nd0q4pe9.wasm";var init_tree_sitter_javascript=()=>{};var highlights_default2="./highlights-eq9cgrbb.scm";var init_highlights2=()=>{};var tree_sitter_typescript_default="./tree-sitter-typescript-zxjzwt75.wasm";var init_tree_sitter_typescript=()=>{};var highlights_default3="./highlights-r812a2qc.scm";var init_highlights3=()=>{};var tree_sitter_markdown_default="./tree-sitter-markdown-411r6y9b.wasm";var init_tree_sitter_markdown=()=>{};var injections_default="./injections-73j83es3.scm";var init_injections=()=>{};var highlights_default4="./highlights-x6tmsnaa.scm";var init_highlights4=()=>{};var tree_sitter_markdown_inline_default="./tree-sitter-markdown_inline-j5349f42.wasm";var init_tree_sitter_markdown_inline=()=>{};var highlights_default5="./highlights-hk7bwhj4.scm";var init_highlights5=()=>{};var tree_sitter_zig_default="./tree-sitter-zig-e78zbjpm.wasm";var init_tree_sitter_zig=()=>{};import{EventEmitter}from"events";import{Buffer as Buffer2}from"buffer";import{Buffer as Buffer3}from"buffer";import{EventEmitter as EventEmitter2}from"events";import{resolve as resolve7,dirname as dirname9}from"path";import{fileURLToPath as fileURLToPath2}from"url";import{resolve as resolve22,isAbsolute,parse as parse2}from"path";import{existsSync as existsSync33}from"fs";import{basename as basename7,join as join44}from"path";import os2 from"os";import path2 from"path";import{EventEmitter as EventEmitter3}from"events";import path22 from"path";import{readFile as readFile22,writeFile as writeFile22,mkdir as mkdir22}from"fs/promises";import*as path4 from"path";import{mkdir as mkdir9,readFile as readFile13,writeFile as writeFile6}from"fs/promises";import*as path3 from"path";import{readdir as readdir7}from"fs/promises";import{dlopen,toArrayBuffer as toArrayBuffer4,JSCallback,ptr as ptr4}from"bun:ffi";import{existsSync as existsSync210,writeFileSync as writeFileSync11}from"fs";import{EventEmitter as EventEmitter4}from"events";import{toArrayBuffer,ptr}from"bun:ffi";import{ptr as ptr2,toArrayBuffer as toArrayBuffer2}from"bun:ffi";import{ptr as ptr3,toArrayBuffer as toArrayBuffer3}from"bun:ffi";import{EventEmitter as EventEmitter5}from"events";import util3 from"util";import{EventEmitter as EventEmitter7}from"events";import{Console}from"console";import fs2 from"fs";import path5 from"path";import util22 from"util";import{Writable}from"stream";import{EventEmitter as EventEmitter6}from"events";import{EventEmitter as EventEmitter8}from"events";function __exportSetter2(name,newValue){this[name]=__returnValue2.bind(null,newValue)}function wrapAssembly(lib){function patch(prototype,name,fn){let original=prototype[name];prototype[name]=function(){for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++)args[_key]=arguments[_key];return fn.call(this,original,...args)}}for(let fnName of["setPosition","setMargin","setFlexBasis","setWidth","setHeight","setMinWidth","setMinHeight","setMaxWidth","setMaxHeight","setPadding","setGap"]){let methods={[Unit.Point]:lib.Node.prototype[fnName],[Unit.Percent]:lib.Node.prototype[`${fnName}Percent`],[Unit.Auto]:lib.Node.prototype[`${fnName}Auto`]};patch(lib.Node.prototype,fnName,function(original){for(var _len2=arguments.length,args=Array(_len2>1?_len2-1:0),_key2=1;_key2<_len2;_key2++)args[_key2-1]=arguments[_key2];let value=args.pop(),unit,asNumber;if(value==="auto")unit=Unit.Auto,asNumber=void 0;else if(typeof value==="object")unit=value.unit,asNumber=value.valueOf();else if(unit=typeof value==="string"&&value.endsWith("%")?Unit.Percent:Unit.Point,asNumber=parseFloat(value),value!==void 0&&!Number.isNaN(value)&&Number.isNaN(asNumber))throw Error(`Invalid value ${value} for ${fnName}`);if(!methods[unit])throw Error(`Failed to execute "${fnName}": Unsupported unit '${value}'`);if(asNumber!==void 0)return methods[unit].call(this,...args,asNumber);else return methods[unit].call(this,...args)})}function wrapMeasureFunction(measureFunction){return lib.MeasureCallback.implement({measure:function(){let{width,height:height2}=measureFunction(...arguments);return{width:width??NaN,height:height2??NaN}}})}patch(lib.Node.prototype,"setMeasureFunc",function(original,measureFunc){if(measureFunc)return original.call(this,wrapMeasureFunction(measureFunc));else return this.unsetMeasureFunc()});function wrapDirtiedFunc(dirtiedFunction){return lib.DirtiedCallback.implement({dirtied:dirtiedFunction})}return patch(lib.Node.prototype,"setDirtiedFunc",function(original,dirtiedFunc){original.call(this,wrapDirtiedFunc(dirtiedFunc))}),patch(lib.Config.prototype,"free",function(){lib.Config.destroy(this)}),patch(lib.Node,"create",(_,config)=>{return config?lib.Node.createWithConfig(config):lib.Node.createDefault()}),patch(lib.Node.prototype,"free",function(){lib.Node.destroy(this)}),patch(lib.Node.prototype,"freeRecursive",function(){for(let t=0,T=this.getChildCount();t<T;++t)this.getChild(0).freeRecursive();this.free()}),patch(lib.Node.prototype,"calculateLayout",function(original){let width=arguments.length>1&&arguments[1]!==void 0?arguments[1]:NaN,height2=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,direction=arguments.length>3&&arguments[3]!==void 0?arguments[3]:Direction.LTR;return original.call(this,width,height2,direction)}),{Config:lib.Config,Node:lib.Node,...YGEnums_default}}function isValidBorderStyle(value){return typeof value==="string"&&VALID_BORDER_STYLES.includes(value)}function parseBorderStyle(value,fallback="single"){if(isValidBorderStyle(value))return value;if(value!==void 0&&value!==null)console.warn(`Invalid borderStyle "${value}", falling back to "${fallback}". Valid values are: ${VALID_BORDER_STYLES.join(", ")}`);return fallback}function getBorderFromSides(sides){let result=[];if(sides.top)result.push("top");if(sides.right)result.push("right");if(sides.bottom)result.push("bottom");if(sides.left)result.push("left");return result.length>0?result:!1}function getBorderSides(border){return border===!0?{top:!0,right:!0,bottom:!0,left:!0}:Array.isArray(border)?{top:border.includes("top"),right:border.includes("right"),bottom:border.includes("bottom"),left:border.includes("left")}:{top:!1,right:!1,bottom:!1,left:!1}}function borderCharsToArray(chars){let array=new Uint32Array(11);return array[0]=chars.topLeft.codePointAt(0),array[1]=chars.topRight.codePointAt(0),array[2]=chars.bottomLeft.codePointAt(0),array[3]=chars.bottomRight.codePointAt(0),array[4]=chars.horizontal.codePointAt(0),array[5]=chars.vertical.codePointAt(0),array[6]=chars.topT.codePointAt(0),array[7]=chars.bottomT.codePointAt(0),array[8]=chars.leftT.codePointAt(0),array[9]=chars.rightT.codePointAt(0),array[10]=chars.cross.codePointAt(0),array}class KeyEvent{name;ctrl;meta;shift;option;sequence;number;raw;eventType;source;code;super;hyper;capsLock;numLock;baseCode;repeated;_defaultPrevented=!1;_propagationStopped=!1;constructor(key){this.name=key.name,this.ctrl=key.ctrl,this.meta=key.meta,this.shift=key.shift,this.option=key.option,this.sequence=key.sequence,this.number=key.number,this.raw=key.raw,this.eventType=key.eventType,this.source=key.source,this.code=key.code,this.super=key.super,this.hyper=key.hyper,this.capsLock=key.capsLock,this.numLock=key.numLock,this.baseCode=key.baseCode,this.repeated=key.repeated}get defaultPrevented(){return this._defaultPrevented}get propagationStopped(){return this._propagationStopped}preventDefault(){this._defaultPrevented=!0}stopPropagation(){this._propagationStopped=!0}}class PasteEvent{type="paste";bytes;metadata;_defaultPrevented=!1;_propagationStopped=!1;constructor(bytes,metadata){this.bytes=bytes,this.metadata=metadata}get defaultPrevented(){return this._defaultPrevented}get propagationStopped(){return this._propagationStopped}preventDefault(){this._defaultPrevented=!0}stopPropagation(){this._propagationStopped=!0}}class RGBA{buffer;constructor(buffer2){this.buffer=buffer2}static fromArray(array){return new RGBA(array)}static fromValues(r,g,b2,a=1){return new RGBA(new Float32Array([r,g,b2,a]))}static fromInts(r,g,b2,a=255){return new RGBA(new Float32Array([r/255,g/255,b2/255,a/255]))}static fromHex(hex){return hexToRgb(hex)}toInts(){return[Math.round(this.r*255),Math.round(this.g*255),Math.round(this.b*255),Math.round(this.a*255)]}get r(){return this.buffer[0]}set r(value){this.buffer[0]=value}get g(){return this.buffer[1]}set g(value){this.buffer[1]=value}get b(){return this.buffer[2]}set b(value){this.buffer[2]=value}get a(){return this.buffer[3]}set a(value){this.buffer[3]=value}map(fn){return[fn(this.r),fn(this.g),fn(this.b),fn(this.a)]}toString(){return`rgba(${this.r.toFixed(2)}, ${this.g.toFixed(2)}, ${this.b.toFixed(2)}, ${this.a.toFixed(2)})`}equals(other){if(!other)return!1;return this.r===other.r&&this.g===other.g&&this.b===other.b&&this.a===other.a}}function hexToRgb(hex){if(hex=hex.replace(/^#/,""),hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];else if(hex.length===4)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]+hex[3]+hex[3];if(!/^[0-9A-Fa-f]{6}$/.test(hex)&&!/^[0-9A-Fa-f]{8}$/.test(hex))return console.warn(`Invalid hex color: ${hex}, defaulting to magenta`),RGBA.fromValues(1,0,1,1);let r=parseInt(hex.substring(0,2),16)/255,g=parseInt(hex.substring(2,4),16)/255,b2=parseInt(hex.substring(4,6),16)/255,a=hex.length===8?parseInt(hex.substring(6,8),16)/255:1;return RGBA.fromValues(r,g,b2,a)}function rgbToHex(rgb){return"#"+(rgb.a===1?[rgb.r,rgb.g,rgb.b]:[rgb.r,rgb.g,rgb.b,rgb.a]).map((x)=>{let hex=Math.floor(Math.max(0,Math.min(1,x)*255)).toString(16);return hex.length===1?"0"+hex:hex}).join("")}function hsvToRgb(h,s,v){let r=0,g=0,b2=0,i2=Math.floor(h/60)%6,f=h/60-Math.floor(h/60),p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s);switch(i2){case 0:r=v,g=t,b2=p;break;case 1:r=q,g=v,b2=p;break;case 2:r=p,g=v,b2=t;break;case 3:r=p,g=q,b2=v;break;case 4:r=t,g=p,b2=v;break;case 5:r=v,g=p,b2=q;break}return RGBA.fromValues(r,g,b2,1)}function parseColor(color){if(typeof color==="string"){let lowerColor=color.toLowerCase();if(lowerColor==="transparent")return RGBA.fromValues(0,0,0,0);if(CSS_COLOR_NAMES[lowerColor])return hexToRgb(CSS_COLOR_NAMES[lowerColor]);return hexToRgb(color)}return color}function parseColorTags(text){let segments=[],currentIndex=0,colorTagRegex=/<c(\d+)>(.*?)<\/c\d+>/g,lastIndex=0,match;while((match=colorTagRegex.exec(text))!==null){if(match.index>lastIndex){let plainText=text.slice(lastIndex,match.index);if(plainText)segments.push({text:plainText,colorIndex:0})}let colorIndex=parseInt(match[1])-1,taggedText=match[2];segments.push({text:taggedText,colorIndex:Math.max(0,colorIndex)}),lastIndex=match.index+match[0].length}if(lastIndex<text.length){let remainingText=text.slice(lastIndex);if(remainingText)segments.push({text:remainingText,colorIndex:0})}return segments}function getParsedFont(fontKey){if(!parsedFonts[fontKey]){let fontDef=fonts[fontKey],parsedChars={};for(let[char,lines]of Object.entries(fontDef.chars))parsedChars[char]=lines.map((line)=>parseColorTags(line));parsedFonts[fontKey]={...fontDef,colors:fontDef.colors||1,chars:parsedChars}}return parsedFonts[fontKey]}function measureText({text,font="tiny"}){let fontDef=getParsedFont(font);if(!fontDef)return console.warn(`Font '${font}' not found`),{width:0,height:0};let currentX=0;for(let i2=0;i2<text.length;i2++){let char=text[i2].toUpperCase(),charDef=fontDef.chars[char];if(!charDef){let spaceChar=fontDef.chars[" "];if(spaceChar&&spaceChar[0]){let spaceWidth=0;for(let segment of spaceChar[0])spaceWidth+=segment.text.length;currentX+=spaceWidth}else currentX+=1;continue}let charWidth=0;if(charDef[0])for(let segment of charDef[0])charWidth+=segment.text.length;if(currentX+=charWidth,i2<text.length-1)currentX+=fontDef.letterspace_size}return{width:currentX,height:fontDef.lines}}function getCharacterPositions(text,font="tiny"){let fontDef=getParsedFont(font);if(!fontDef)return[0];let positions=[0],currentX=0;for(let i2=0;i2<text.length;i2++){let char=text[i2].toUpperCase(),charDef=fontDef.chars[char],charWidth=0;if(!charDef){let spaceChar=fontDef.chars[" "];if(spaceChar&&spaceChar[0])for(let segment of spaceChar[0])charWidth+=segment.text.length;else charWidth=1}else if(charDef[0])for(let segment of charDef[0])charWidth+=segment.text.length;if(currentX+=charWidth,i2<text.length-1)currentX+=fontDef.letterspace_size;positions.push(currentX)}return positions}function coordinateToCharacterIndex(x,text,font="tiny"){let positions=getCharacterPositions(text,font);if(x<0)return 0;for(let i2=0;i2<positions.length-1;i2++){let currentPos=positions[i2],nextPos=positions[i2+1];if(x>=currentPos&&x<nextPos){let charMidpoint=currentPos+(nextPos-currentPos)/2;return x<charMidpoint?i2:i2+1}}if(positions.length>0&&x>=positions[positions.length-1])return text.length;return 0}function renderFontToFrameBuffer(buffer2,{text,x=0,y=0,color=[RGBA.fromInts(255,255,255,255)],backgroundColor=RGBA.fromInts(0,0,0,255),font="tiny"}){let{width,height:height2}=buffer2,fontDef=getParsedFont(font);if(!fontDef)return console.warn(`Font '${font}' not found`),{width:0,height:0};let colors4=Array.isArray(color)?color:[color];if(y<0||y+fontDef.lines>height2)return{width:0,height:fontDef.lines};let currentX=x,startX=x;for(let i2=0;i2<text.length;i2++){let char=text[i2].toUpperCase(),charDef=fontDef.chars[char];if(!charDef){let spaceChar=fontDef.chars[" "];if(spaceChar&&spaceChar[0]){let spaceWidth=0;for(let segment of spaceChar[0])spaceWidth+=segment.text.length;currentX+=spaceWidth}else currentX+=1;continue}let charWidth=0;if(charDef[0])for(let segment of charDef[0])charWidth+=segment.text.length;if(currentX>=width)break;if(currentX+charWidth<0){currentX+=charWidth+fontDef.letterspace_size;continue}for(let lineIdx=0;lineIdx<fontDef.lines&&lineIdx<charDef.length;lineIdx++){let segments=charDef[lineIdx],renderY=y+lineIdx;if(renderY>=0&&renderY<height2){let segmentX=currentX;for(let segment of segments){let segmentColor=colors4[segment.colorIndex]||colors4[0];for(let charIdx=0;charIdx<segment.text.length;charIdx++){let renderX=segmentX+charIdx;if(renderX>=0&&renderX<width){let fontChar=segment.text[charIdx];if(fontChar!==" ")buffer2.setCellWithAlphaBlending(renderX,renderY,fontChar,parseColor(segmentColor),parseColor(backgroundColor))}}segmentX+=segment.text.length}}}if(currentX+=charWidth,i2<text.length-1)currentX+=fontDef.letterspace_size}return{width:currentX-startX,height:fontDef.lines}}function getBaseAttributes(attr){return attr&ATTRIBUTE_BASE_MASK}function createTextAttributes({bold=!1,italic=!1,underline=!1,dim=!1,blink=!1,inverse=!1,hidden=!1,strikethrough=!1}={}){let attributes=TextAttributes.NONE;if(bold)attributes|=TextAttributes.BOLD;if(italic)attributes|=TextAttributes.ITALIC;if(underline)attributes|=TextAttributes.UNDERLINE;if(dim)attributes|=TextAttributes.DIM;if(blink)attributes|=TextAttributes.BLINK;if(inverse)attributes|=TextAttributes.INVERSE;if(hidden)attributes|=TextAttributes.HIDDEN;if(strikethrough)attributes|=TextAttributes.STRIKETHROUGH;return attributes}function attributesWithLink(baseAttributes,linkId){let base=baseAttributes&ATTRIBUTE_BASE_MASK2,linkBits=(linkId&LINK_ID_PAYLOAD_MASK)<<LINK_ID_SHIFT;return base|linkBits}function getLinkId(attributes){return attributes>>>LINK_ID_SHIFT&LINK_ID_PAYLOAD_MASK}function visualizeRenderableTree(renderable,maxDepth=10){function buildTreeLines(node,prefix="",parentPrefix="",isLastChild=!0,depth=0){if(depth>=maxDepth)return[`${prefix}${node.id} ... (max depth reached)`];let lines=[],children=node.getChildren();if(lines.push(`${prefix}${node.id}`),children.length>0){let lastChildIndex=children.length-1;children.forEach((child,index)=>{let childIsLast=index===lastChildIndex,connector=childIsLast?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",childPrefix=parentPrefix+(isLastChild?" ":"\u2502 "),childLines=buildTreeLines(child,childPrefix+connector,childPrefix,childIsLast,depth+1);lines.push(...childLines)})}return lines}let treeLines=buildTreeLines(renderable);console.log(`Renderable Tree:
|
|
1435
|
+
`);return panes[1]||panes[0]}catch{return rightPane}}}function ensureSession3(sessionName){try{execSync13(`tmux has-session -t '${sessionName}' 2>/dev/null`,{stdio:"ignore"})}catch{try{execSync13(`tmux new-session -d -s '${sessionName}'`,{stdio:"ignore"})}catch{}}}function attachProjectWindow(rightPane,targetSession,windowIndex){let pane=resolveRightPane(rightPane);if(ensureSession3(targetSession),windowIndex!==void 0)try{execSync13(`tmux select-window -t '${targetSession}:${windowIndex}'`,{stdio:"ignore"})}catch{}try{execSync13(`tmux respawn-pane -k -t ${pane} "TMUX='' tmux attach-session -t '${targetSession}'"`,{stdio:"ignore"})}catch{}}function setupKeybindings(session){try{execSync13(`tmux bind-key -T ${KEY_TABLE} Tab select-pane -t ${session}:0.1 \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync13(`tmux bind-key -T ${KEY_TABLE} C-b if-shell "[ $(tmux display-message -p '#{pane_width}' -t ${session}:0.0) -gt 5 ]" "resize-pane -t ${session}:0.0 -x 0" "resize-pane -t ${session}:0.0 -x ${NAV_WIDTH}" \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync13(`tmux bind-key -T ${KEY_TABLE} C-t send-keys -t ${session}:0.1 C-b c \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync13(`tmux bind-key -T ${KEY_TABLE} 'C-\\' run-shell "tmux kill-session -t ${session}"`,{stdio:"ignore"}),execSync13(`tmux set-hook -t ${session} client-session-changed "switch-client -T ${KEY_TABLE}"`,{stdio:"ignore"}),execSync13(`tmux switch-client -T ${KEY_TABLE}`,{stdio:"ignore"})}catch{}}function applyTmuxStyle(session){try{let cmds=[`set-option -t ${session} pane-border-style 'fg=${tmuxStyle.inactiveBorder}'`,`set-option -t ${session} pane-active-border-style 'fg=${tmuxStyle.activeBorder}'`,`set-option -t ${session} status off`,`set-option -t ${session} mouse on`];for(let cmd of cmds)execSync13(`tmux ${cmd}`,{stdio:"ignore"})}catch{}}function cleanup(session=SESSION_NAME){try{execSync13(`tmux unbind-key -T ${KEY_TABLE} Tab 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux unbind-key -T ${KEY_TABLE} C-b 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux unbind-key -T ${KEY_TABLE} C-t 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux unbind-key -T ${KEY_TABLE} 'C-\\' 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux set-hook -u -t ${session} client-session-changed 2>/dev/null`,{stdio:"ignore"}),execSync13(`tmux kill-session -t ${session} 2>/dev/null`,{stdio:"ignore"})}catch{}}function attachTuiSession(){spawnSync2("tmux",["attach-session","-t",SESSION_NAME],{stdio:"inherit"})}var SESSION_NAME="genie-tui",KEY_TABLE="genie-tui",NAV_WIDTH=30;var init_tmux2=__esm(()=>{init_theme2()});var highlights_default="./highlights-ghv9g403.scm";var init_highlights=()=>{};var tree_sitter_javascript_default="./tree-sitter-javascript-nd0q4pe9.wasm";var init_tree_sitter_javascript=()=>{};var highlights_default2="./highlights-eq9cgrbb.scm";var init_highlights2=()=>{};var tree_sitter_typescript_default="./tree-sitter-typescript-zxjzwt75.wasm";var init_tree_sitter_typescript=()=>{};var highlights_default3="./highlights-r812a2qc.scm";var init_highlights3=()=>{};var tree_sitter_markdown_default="./tree-sitter-markdown-411r6y9b.wasm";var init_tree_sitter_markdown=()=>{};var injections_default="./injections-73j83es3.scm";var init_injections=()=>{};var highlights_default4="./highlights-x6tmsnaa.scm";var init_highlights4=()=>{};var tree_sitter_markdown_inline_default="./tree-sitter-markdown_inline-j5349f42.wasm";var init_tree_sitter_markdown_inline=()=>{};var highlights_default5="./highlights-hk7bwhj4.scm";var init_highlights5=()=>{};var tree_sitter_zig_default="./tree-sitter-zig-e78zbjpm.wasm";var init_tree_sitter_zig=()=>{};import{EventEmitter}from"events";import{Buffer as Buffer2}from"buffer";import{Buffer as Buffer3}from"buffer";import{EventEmitter as EventEmitter2}from"events";import{resolve as resolve7,dirname as dirname9}from"path";import{fileURLToPath as fileURLToPath2}from"url";import{resolve as resolve22,isAbsolute,parse as parse2}from"path";import{existsSync as existsSync33}from"fs";import{basename as basename7,join as join44}from"path";import os2 from"os";import path2 from"path";import{EventEmitter as EventEmitter3}from"events";import path22 from"path";import{readFile as readFile22,writeFile as writeFile22,mkdir as mkdir22}from"fs/promises";import*as path4 from"path";import{mkdir as mkdir9,readFile as readFile13,writeFile as writeFile6}from"fs/promises";import*as path3 from"path";import{readdir as readdir7}from"fs/promises";import{dlopen,toArrayBuffer as toArrayBuffer4,JSCallback,ptr as ptr4}from"bun:ffi";import{existsSync as existsSync210,writeFileSync as writeFileSync11}from"fs";import{EventEmitter as EventEmitter4}from"events";import{toArrayBuffer,ptr}from"bun:ffi";import{ptr as ptr2,toArrayBuffer as toArrayBuffer2}from"bun:ffi";import{ptr as ptr3,toArrayBuffer as toArrayBuffer3}from"bun:ffi";import{EventEmitter as EventEmitter5}from"events";import util3 from"util";import{EventEmitter as EventEmitter7}from"events";import{Console}from"console";import fs2 from"fs";import path5 from"path";import util22 from"util";import{Writable}from"stream";import{EventEmitter as EventEmitter6}from"events";import{EventEmitter as EventEmitter8}from"events";function __exportSetter2(name,newValue){this[name]=__returnValue2.bind(null,newValue)}function wrapAssembly(lib){function patch(prototype,name,fn){let original=prototype[name];prototype[name]=function(){for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++)args[_key]=arguments[_key];return fn.call(this,original,...args)}}for(let fnName of["setPosition","setMargin","setFlexBasis","setWidth","setHeight","setMinWidth","setMinHeight","setMaxWidth","setMaxHeight","setPadding","setGap"]){let methods={[Unit.Point]:lib.Node.prototype[fnName],[Unit.Percent]:lib.Node.prototype[`${fnName}Percent`],[Unit.Auto]:lib.Node.prototype[`${fnName}Auto`]};patch(lib.Node.prototype,fnName,function(original){for(var _len2=arguments.length,args=Array(_len2>1?_len2-1:0),_key2=1;_key2<_len2;_key2++)args[_key2-1]=arguments[_key2];let value=args.pop(),unit,asNumber;if(value==="auto")unit=Unit.Auto,asNumber=void 0;else if(typeof value==="object")unit=value.unit,asNumber=value.valueOf();else if(unit=typeof value==="string"&&value.endsWith("%")?Unit.Percent:Unit.Point,asNumber=parseFloat(value),value!==void 0&&!Number.isNaN(value)&&Number.isNaN(asNumber))throw Error(`Invalid value ${value} for ${fnName}`);if(!methods[unit])throw Error(`Failed to execute "${fnName}": Unsupported unit '${value}'`);if(asNumber!==void 0)return methods[unit].call(this,...args,asNumber);else return methods[unit].call(this,...args)})}function wrapMeasureFunction(measureFunction){return lib.MeasureCallback.implement({measure:function(){let{width,height:height2}=measureFunction(...arguments);return{width:width??NaN,height:height2??NaN}}})}patch(lib.Node.prototype,"setMeasureFunc",function(original,measureFunc){if(measureFunc)return original.call(this,wrapMeasureFunction(measureFunc));else return this.unsetMeasureFunc()});function wrapDirtiedFunc(dirtiedFunction){return lib.DirtiedCallback.implement({dirtied:dirtiedFunction})}return patch(lib.Node.prototype,"setDirtiedFunc",function(original,dirtiedFunc){original.call(this,wrapDirtiedFunc(dirtiedFunc))}),patch(lib.Config.prototype,"free",function(){lib.Config.destroy(this)}),patch(lib.Node,"create",(_,config)=>{return config?lib.Node.createWithConfig(config):lib.Node.createDefault()}),patch(lib.Node.prototype,"free",function(){lib.Node.destroy(this)}),patch(lib.Node.prototype,"freeRecursive",function(){for(let t=0,T=this.getChildCount();t<T;++t)this.getChild(0).freeRecursive();this.free()}),patch(lib.Node.prototype,"calculateLayout",function(original){let width=arguments.length>1&&arguments[1]!==void 0?arguments[1]:NaN,height2=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,direction=arguments.length>3&&arguments[3]!==void 0?arguments[3]:Direction.LTR;return original.call(this,width,height2,direction)}),{Config:lib.Config,Node:lib.Node,...YGEnums_default}}function isValidBorderStyle(value){return typeof value==="string"&&VALID_BORDER_STYLES.includes(value)}function parseBorderStyle(value,fallback="single"){if(isValidBorderStyle(value))return value;if(value!==void 0&&value!==null)console.warn(`Invalid borderStyle "${value}", falling back to "${fallback}". Valid values are: ${VALID_BORDER_STYLES.join(", ")}`);return fallback}function getBorderFromSides(sides){let result=[];if(sides.top)result.push("top");if(sides.right)result.push("right");if(sides.bottom)result.push("bottom");if(sides.left)result.push("left");return result.length>0?result:!1}function getBorderSides(border){return border===!0?{top:!0,right:!0,bottom:!0,left:!0}:Array.isArray(border)?{top:border.includes("top"),right:border.includes("right"),bottom:border.includes("bottom"),left:border.includes("left")}:{top:!1,right:!1,bottom:!1,left:!1}}function borderCharsToArray(chars){let array=new Uint32Array(11);return array[0]=chars.topLeft.codePointAt(0),array[1]=chars.topRight.codePointAt(0),array[2]=chars.bottomLeft.codePointAt(0),array[3]=chars.bottomRight.codePointAt(0),array[4]=chars.horizontal.codePointAt(0),array[5]=chars.vertical.codePointAt(0),array[6]=chars.topT.codePointAt(0),array[7]=chars.bottomT.codePointAt(0),array[8]=chars.leftT.codePointAt(0),array[9]=chars.rightT.codePointAt(0),array[10]=chars.cross.codePointAt(0),array}class KeyEvent{name;ctrl;meta;shift;option;sequence;number;raw;eventType;source;code;super;hyper;capsLock;numLock;baseCode;repeated;_defaultPrevented=!1;_propagationStopped=!1;constructor(key){this.name=key.name,this.ctrl=key.ctrl,this.meta=key.meta,this.shift=key.shift,this.option=key.option,this.sequence=key.sequence,this.number=key.number,this.raw=key.raw,this.eventType=key.eventType,this.source=key.source,this.code=key.code,this.super=key.super,this.hyper=key.hyper,this.capsLock=key.capsLock,this.numLock=key.numLock,this.baseCode=key.baseCode,this.repeated=key.repeated}get defaultPrevented(){return this._defaultPrevented}get propagationStopped(){return this._propagationStopped}preventDefault(){this._defaultPrevented=!0}stopPropagation(){this._propagationStopped=!0}}class PasteEvent{type="paste";bytes;metadata;_defaultPrevented=!1;_propagationStopped=!1;constructor(bytes,metadata){this.bytes=bytes,this.metadata=metadata}get defaultPrevented(){return this._defaultPrevented}get propagationStopped(){return this._propagationStopped}preventDefault(){this._defaultPrevented=!0}stopPropagation(){this._propagationStopped=!0}}class RGBA{buffer;constructor(buffer2){this.buffer=buffer2}static fromArray(array){return new RGBA(array)}static fromValues(r,g,b2,a=1){return new RGBA(new Float32Array([r,g,b2,a]))}static fromInts(r,g,b2,a=255){return new RGBA(new Float32Array([r/255,g/255,b2/255,a/255]))}static fromHex(hex){return hexToRgb(hex)}toInts(){return[Math.round(this.r*255),Math.round(this.g*255),Math.round(this.b*255),Math.round(this.a*255)]}get r(){return this.buffer[0]}set r(value){this.buffer[0]=value}get g(){return this.buffer[1]}set g(value){this.buffer[1]=value}get b(){return this.buffer[2]}set b(value){this.buffer[2]=value}get a(){return this.buffer[3]}set a(value){this.buffer[3]=value}map(fn){return[fn(this.r),fn(this.g),fn(this.b),fn(this.a)]}toString(){return`rgba(${this.r.toFixed(2)}, ${this.g.toFixed(2)}, ${this.b.toFixed(2)}, ${this.a.toFixed(2)})`}equals(other){if(!other)return!1;return this.r===other.r&&this.g===other.g&&this.b===other.b&&this.a===other.a}}function hexToRgb(hex){if(hex=hex.replace(/^#/,""),hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];else if(hex.length===4)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]+hex[3]+hex[3];if(!/^[0-9A-Fa-f]{6}$/.test(hex)&&!/^[0-9A-Fa-f]{8}$/.test(hex))return console.warn(`Invalid hex color: ${hex}, defaulting to magenta`),RGBA.fromValues(1,0,1,1);let r=parseInt(hex.substring(0,2),16)/255,g=parseInt(hex.substring(2,4),16)/255,b2=parseInt(hex.substring(4,6),16)/255,a=hex.length===8?parseInt(hex.substring(6,8),16)/255:1;return RGBA.fromValues(r,g,b2,a)}function rgbToHex(rgb){return"#"+(rgb.a===1?[rgb.r,rgb.g,rgb.b]:[rgb.r,rgb.g,rgb.b,rgb.a]).map((x)=>{let hex=Math.floor(Math.max(0,Math.min(1,x)*255)).toString(16);return hex.length===1?"0"+hex:hex}).join("")}function hsvToRgb(h,s,v){let r=0,g=0,b2=0,i2=Math.floor(h/60)%6,f=h/60-Math.floor(h/60),p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s);switch(i2){case 0:r=v,g=t,b2=p;break;case 1:r=q,g=v,b2=p;break;case 2:r=p,g=v,b2=t;break;case 3:r=p,g=q,b2=v;break;case 4:r=t,g=p,b2=v;break;case 5:r=v,g=p,b2=q;break}return RGBA.fromValues(r,g,b2,1)}function parseColor(color){if(typeof color==="string"){let lowerColor=color.toLowerCase();if(lowerColor==="transparent")return RGBA.fromValues(0,0,0,0);if(CSS_COLOR_NAMES[lowerColor])return hexToRgb(CSS_COLOR_NAMES[lowerColor]);return hexToRgb(color)}return color}function parseColorTags(text){let segments=[],currentIndex=0,colorTagRegex=/<c(\d+)>(.*?)<\/c\d+>/g,lastIndex=0,match;while((match=colorTagRegex.exec(text))!==null){if(match.index>lastIndex){let plainText=text.slice(lastIndex,match.index);if(plainText)segments.push({text:plainText,colorIndex:0})}let colorIndex=parseInt(match[1])-1,taggedText=match[2];segments.push({text:taggedText,colorIndex:Math.max(0,colorIndex)}),lastIndex=match.index+match[0].length}if(lastIndex<text.length){let remainingText=text.slice(lastIndex);if(remainingText)segments.push({text:remainingText,colorIndex:0})}return segments}function getParsedFont(fontKey){if(!parsedFonts[fontKey]){let fontDef=fonts[fontKey],parsedChars={};for(let[char,lines]of Object.entries(fontDef.chars))parsedChars[char]=lines.map((line)=>parseColorTags(line));parsedFonts[fontKey]={...fontDef,colors:fontDef.colors||1,chars:parsedChars}}return parsedFonts[fontKey]}function measureText({text,font="tiny"}){let fontDef=getParsedFont(font);if(!fontDef)return console.warn(`Font '${font}' not found`),{width:0,height:0};let currentX=0;for(let i2=0;i2<text.length;i2++){let char=text[i2].toUpperCase(),charDef=fontDef.chars[char];if(!charDef){let spaceChar=fontDef.chars[" "];if(spaceChar&&spaceChar[0]){let spaceWidth=0;for(let segment of spaceChar[0])spaceWidth+=segment.text.length;currentX+=spaceWidth}else currentX+=1;continue}let charWidth=0;if(charDef[0])for(let segment of charDef[0])charWidth+=segment.text.length;if(currentX+=charWidth,i2<text.length-1)currentX+=fontDef.letterspace_size}return{width:currentX,height:fontDef.lines}}function getCharacterPositions(text,font="tiny"){let fontDef=getParsedFont(font);if(!fontDef)return[0];let positions=[0],currentX=0;for(let i2=0;i2<text.length;i2++){let char=text[i2].toUpperCase(),charDef=fontDef.chars[char],charWidth=0;if(!charDef){let spaceChar=fontDef.chars[" "];if(spaceChar&&spaceChar[0])for(let segment of spaceChar[0])charWidth+=segment.text.length;else charWidth=1}else if(charDef[0])for(let segment of charDef[0])charWidth+=segment.text.length;if(currentX+=charWidth,i2<text.length-1)currentX+=fontDef.letterspace_size;positions.push(currentX)}return positions}function coordinateToCharacterIndex(x,text,font="tiny"){let positions=getCharacterPositions(text,font);if(x<0)return 0;for(let i2=0;i2<positions.length-1;i2++){let currentPos=positions[i2],nextPos=positions[i2+1];if(x>=currentPos&&x<nextPos){let charMidpoint=currentPos+(nextPos-currentPos)/2;return x<charMidpoint?i2:i2+1}}if(positions.length>0&&x>=positions[positions.length-1])return text.length;return 0}function renderFontToFrameBuffer(buffer2,{text,x=0,y=0,color=[RGBA.fromInts(255,255,255,255)],backgroundColor=RGBA.fromInts(0,0,0,255),font="tiny"}){let{width,height:height2}=buffer2,fontDef=getParsedFont(font);if(!fontDef)return console.warn(`Font '${font}' not found`),{width:0,height:0};let colors4=Array.isArray(color)?color:[color];if(y<0||y+fontDef.lines>height2)return{width:0,height:fontDef.lines};let currentX=x,startX=x;for(let i2=0;i2<text.length;i2++){let char=text[i2].toUpperCase(),charDef=fontDef.chars[char];if(!charDef){let spaceChar=fontDef.chars[" "];if(spaceChar&&spaceChar[0]){let spaceWidth=0;for(let segment of spaceChar[0])spaceWidth+=segment.text.length;currentX+=spaceWidth}else currentX+=1;continue}let charWidth=0;if(charDef[0])for(let segment of charDef[0])charWidth+=segment.text.length;if(currentX>=width)break;if(currentX+charWidth<0){currentX+=charWidth+fontDef.letterspace_size;continue}for(let lineIdx=0;lineIdx<fontDef.lines&&lineIdx<charDef.length;lineIdx++){let segments=charDef[lineIdx],renderY=y+lineIdx;if(renderY>=0&&renderY<height2){let segmentX=currentX;for(let segment of segments){let segmentColor=colors4[segment.colorIndex]||colors4[0];for(let charIdx=0;charIdx<segment.text.length;charIdx++){let renderX=segmentX+charIdx;if(renderX>=0&&renderX<width){let fontChar=segment.text[charIdx];if(fontChar!==" ")buffer2.setCellWithAlphaBlending(renderX,renderY,fontChar,parseColor(segmentColor),parseColor(backgroundColor))}}segmentX+=segment.text.length}}}if(currentX+=charWidth,i2<text.length-1)currentX+=fontDef.letterspace_size}return{width:currentX-startX,height:fontDef.lines}}function getBaseAttributes(attr){return attr&ATTRIBUTE_BASE_MASK}function createTextAttributes({bold=!1,italic=!1,underline=!1,dim=!1,blink=!1,inverse=!1,hidden=!1,strikethrough=!1}={}){let attributes=TextAttributes.NONE;if(bold)attributes|=TextAttributes.BOLD;if(italic)attributes|=TextAttributes.ITALIC;if(underline)attributes|=TextAttributes.UNDERLINE;if(dim)attributes|=TextAttributes.DIM;if(blink)attributes|=TextAttributes.BLINK;if(inverse)attributes|=TextAttributes.INVERSE;if(hidden)attributes|=TextAttributes.HIDDEN;if(strikethrough)attributes|=TextAttributes.STRIKETHROUGH;return attributes}function attributesWithLink(baseAttributes,linkId){let base=baseAttributes&ATTRIBUTE_BASE_MASK2,linkBits=(linkId&LINK_ID_PAYLOAD_MASK)<<LINK_ID_SHIFT;return base|linkBits}function getLinkId(attributes){return attributes>>>LINK_ID_SHIFT&LINK_ID_PAYLOAD_MASK}function visualizeRenderableTree(renderable,maxDepth=10){function buildTreeLines(node,prefix="",parentPrefix="",isLastChild=!0,depth=0){if(depth>=maxDepth)return[`${prefix}${node.id} ... (max depth reached)`];let lines=[],children=node.getChildren();if(lines.push(`${prefix}${node.id}`),children.length>0){let lastChildIndex=children.length-1;children.forEach((child,index)=>{let childIsLast=index===lastChildIndex,connector=childIsLast?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",childPrefix=parentPrefix+(isLastChild?" ":"\u2502 "),childLines=buildTreeLines(child,childPrefix+connector,childPrefix,childIsLast,depth+1);lines.push(...childLines)})}return lines}let treeLines=buildTreeLines(renderable);console.log(`Renderable Tree:
|
|
1437
1436
|
`+treeLines.join(`
|
|
1438
1437
|
`))}function isStyledText(obj){return obj&&obj[BrandedStyledText]}function stringToStyledText(content){return new StyledText([{__isChunk:!0,text:content}])}function applyStyle(input,style){if(typeof input==="object"&&"__isChunk"in input){let existingChunk=input,fg=style.fg?parseColor(style.fg):existingChunk.fg,bg=style.bg?parseColor(style.bg):existingChunk.bg,newAttrs=createTextAttributes(style),mergedAttrs=existingChunk.attributes?existingChunk.attributes|newAttrs:newAttrs;return{__isChunk:!0,text:existingChunk.text,fg,bg,attributes:mergedAttrs,link:existingChunk.link}}else{let plainTextStr=String(input),fg=style.fg?parseColor(style.fg):void 0,bg=style.bg?parseColor(style.bg):void 0,attributes=createTextAttributes(style);return{__isChunk:!0,text:plainTextStr,fg,bg,attributes}}}function t(strings,...values2){let chunks=[];for(let i2=0;i2<strings.length;i2++){let raw=strings[i2];if(raw)chunks.push({__isChunk:!0,text:raw,attributes:0});let val=values2[i2];if(typeof val==="object"&&"__isChunk"in val)chunks.push(val);else if(val!==void 0){let plainTextStr=String(val);chunks.push({__isChunk:!0,text:plainTextStr,attributes:0})}}return new StyledText(chunks)}function hastToTextChunks(node,syntaxStyle,parentStyles=[]){let chunks=[];if(node.type==="text"){let stylesToMerge=parentStyles.length>0?parentStyles:["default"],mergedStyle=syntaxStyle.mergeStyles(...stylesToMerge);chunks.push({__isChunk:!0,text:node.value,fg:mergedStyle.fg,bg:mergedStyle.bg,attributes:mergedStyle.attributes})}else if(node.type==="element"){let currentStyles=[...parentStyles];if(node.properties?.className){let classes=node.properties.className.split(" ");for(let cls of classes)currentStyles.push(cls)}for(let child of node.children)chunks.push(...hastToTextChunks(child,syntaxStyle,currentStyles))}return chunks}function hastToStyledText(hast,syntaxStyle){let chunks=hastToTextChunks(hast,syntaxStyle);return new StyledText(chunks)}class SystemClock{now(){if(!globalThis.performance||typeof globalThis.performance.now!=="function")throw Error("SystemClock requires globalThis.performance.now()");return globalThis.performance.now()}setTimeout(fn,delayMs){return globalThis.setTimeout(fn,delayMs)}clearTimeout(handle){globalThis.clearTimeout(handle)}setInterval(fn,delayMs){return globalThis.setInterval(fn,delayMs)}clearInterval(handle){globalThis.clearInterval(handle)}}function fromKittyMods(mod){return{shift:!!(mod&1),alt:!!(mod&2),ctrl:!!(mod&4),super:!!(mod&8),hyper:!!(mod&16),meta:!!(mod&32),capsLock:!!(mod&64),numLock:!!(mod&128)}}function parseKittySpecialKey(sequence){let match=/^\x1b\[(\d+);(\d+):(\d+)([A-Z~])$/.exec(sequence);if(!match)return null;let keyNumOrOne=match[1],modifierStr=match[2],eventTypeStr=match[3],terminator=match[4],keyName;if(terminator==="~")keyName=tildeKeyMap[keyNumOrOne];else{if(keyNumOrOne!=="1")return null;keyName=functionalKeyMap[terminator]}if(!keyName)return null;let key={name:keyName,ctrl:!1,meta:!1,shift:!1,option:!1,number:!1,sequence,raw:sequence,eventType:"press",source:"kitty",super:!1,hyper:!1,capsLock:!1,numLock:!1};if(modifierStr){let modifierMask=parseInt(modifierStr,10);if(!isNaN(modifierMask)&&modifierMask>1){let mods=fromKittyMods(modifierMask-1);key.shift=mods.shift,key.ctrl=mods.ctrl,key.meta=mods.alt||mods.meta,key.option=mods.alt,key.super=mods.super,key.hyper=mods.hyper,key.capsLock=mods.capsLock,key.numLock=mods.numLock}}if(eventTypeStr==="1"||!eventTypeStr)key.eventType="press";else if(eventTypeStr==="2")key.eventType="press",key.repeated=!0;else if(eventTypeStr==="3")key.eventType="release";return key}function parseKittyKeyboard(sequence){let specialResult=parseKittySpecialKey(sequence);if(specialResult)return specialResult;let match=/^\x1b\[([^\x1b]+)u$/.exec(sequence);if(!match)return null;let fields=match[1].split(";");if(fields.length<1)return null;let key={name:"",ctrl:!1,meta:!1,shift:!1,option:!1,number:!1,sequence,raw:sequence,eventType:"press",source:"kitty",super:!1,hyper:!1,capsLock:!1,numLock:!1},text="",field1=fields[0]?.split(":")||[],codepointStr=field1[0];if(!codepointStr)return null;let codepoint=parseInt(codepointStr,10);if(isNaN(codepoint))return null;let shiftedCodepoint,baseCodepoint;if(field1[1]){let shifted=parseInt(field1[1],10);if(!isNaN(shifted)&&shifted>0&&shifted<=1114111)shiftedCodepoint=shifted}if(field1[2]){let base=parseInt(field1[2],10);if(!isNaN(base)&&base>0&&base<=1114111)baseCodepoint=base}let knownKey=kittyKeyMap[codepoint];if(knownKey)key.name=knownKey,key.code=`[${codepoint}u`;else if(codepoint===0)key.name="";else if(codepoint>0&&codepoint<=1114111){let char=String.fromCodePoint(codepoint);if(key.name=char,baseCodepoint)key.baseCode=baseCodepoint}else return null;if(fields[1]){let field2=fields[1].split(":"),modifierStr=field2[0],eventTypeStr=field2[1];if(modifierStr){let modifierMask=parseInt(modifierStr,10);if(!isNaN(modifierMask)&&modifierMask>1){let mods=fromKittyMods(modifierMask-1);key.shift=mods.shift,key.ctrl=mods.ctrl,key.meta=mods.alt||mods.meta,key.option=mods.alt,key.super=mods.super,key.hyper=mods.hyper,key.capsLock=mods.capsLock,key.numLock=mods.numLock}}if(eventTypeStr==="1"||!eventTypeStr)key.eventType="press";else if(eventTypeStr==="2")key.eventType="press",key.repeated=!0;else if(eventTypeStr==="3")key.eventType="release";else key.eventType="press"}if(fields[2]){let codepoints=fields[2].split(":");for(let cpStr of codepoints){let cp3=parseInt(cpStr,10);if(!isNaN(cp3)&&cp3>0&&cp3<=1114111)text+=String.fromCodePoint(cp3)}}if(text===""){if(key.name.length>0&&!kittyKeyMap[codepoint])if(key.shift&&shiftedCodepoint)text=String.fromCodePoint(shiftedCodepoint);else if(key.shift&&key.name.length===1)text=key.name.toLocaleUpperCase();else text=key.name}if(key.name===" "&&key.shift&&!key.ctrl&&!key.meta)text=" ";if(text){if(codepoint===0)key.name=text;key.sequence=text}if(codepoint===0&&text==="")return null;return key}class LinearScrollAccel{tick(_now){return 1}reset(){}}class MacOSScrollAccel{opts;lastTickTime=0;velocityHistory=[];historySize=3;streakTimeout=150;minTickInterval=6;constructor(opts={}){this.opts=opts}tick(now=Date.now()){let A=this.opts.A??0.8,tau=this.opts.tau??3,maxMultiplier=this.opts.maxMultiplier??6,dt=this.lastTickTime?now-this.lastTickTime:1/0;if(dt===1/0||dt>this.streakTimeout)return this.lastTickTime=now,this.velocityHistory=[],1;if(dt<this.minTickInterval)return 1;if(this.lastTickTime=now,this.velocityHistory.push(dt),this.velocityHistory.length>this.historySize)this.velocityHistory.shift();let x=100/(this.velocityHistory.reduce((a,b2)=>a+b2,0)/this.velocityHistory.length)/tau,multiplier=1+A*(Math.exp(x)-1);return Math.min(multiplier,maxMultiplier)}reset(){this.lastTickTime=0,this.velocityHistory=[]}}function parseAlign(value){if(value==null)return Align.Auto;switch(value.toLowerCase()){case"auto":return Align.Auto;case"flex-start":return Align.FlexStart;case"center":return Align.Center;case"flex-end":return Align.FlexEnd;case"stretch":return Align.Stretch;case"baseline":return Align.Baseline;case"space-between":return Align.SpaceBetween;case"space-around":return Align.SpaceAround;case"space-evenly":return Align.SpaceEvenly;default:return Align.Auto}}function parseAlignItems(value){if(value==null)return Align.Stretch;switch(value.toLowerCase()){case"auto":return Align.Auto;case"flex-start":return Align.FlexStart;case"center":return Align.Center;case"flex-end":return Align.FlexEnd;case"stretch":return Align.Stretch;case"baseline":return Align.Baseline;case"space-between":return Align.SpaceBetween;case"space-around":return Align.SpaceAround;case"space-evenly":return Align.SpaceEvenly;default:return Align.Stretch}}function parseBoxSizing(value){if(value==null)return BoxSizing.BorderBox;switch(value.toLowerCase()){case"border-box":return BoxSizing.BorderBox;case"content-box":return BoxSizing.ContentBox;default:return BoxSizing.BorderBox}}function parseDimension(value){if(value==null)return Dimension.Width;switch(value.toLowerCase()){case"width":return Dimension.Width;case"height":return Dimension.Height;default:return Dimension.Width}}function parseDirection(value){if(value==null)return Direction.LTR;switch(value.toLowerCase()){case"inherit":return Direction.Inherit;case"ltr":return Direction.LTR;case"rtl":return Direction.RTL;default:return Direction.LTR}}function parseDisplay(value){if(value==null)return Display.Flex;switch(value.toLowerCase()){case"flex":return Display.Flex;case"none":return Display.None;case"contents":return Display.Contents;default:return Display.Flex}}function parseEdge(value){if(value==null)return Edge.All;switch(value.toLowerCase()){case"left":return Edge.Left;case"top":return Edge.Top;case"right":return Edge.Right;case"bottom":return Edge.Bottom;case"start":return Edge.Start;case"end":return Edge.End;case"horizontal":return Edge.Horizontal;case"vertical":return Edge.Vertical;case"all":return Edge.All;default:return Edge.All}}function parseFlexDirection(value){if(value==null)return FlexDirection.Column;switch(value.toLowerCase()){case"column":return FlexDirection.Column;case"column-reverse":return FlexDirection.ColumnReverse;case"row":return FlexDirection.Row;case"row-reverse":return FlexDirection.RowReverse;default:return FlexDirection.Column}}function parseGutter(value){if(value==null)return Gutter.All;switch(value.toLowerCase()){case"column":return Gutter.Column;case"row":return Gutter.Row;case"all":return Gutter.All;default:return Gutter.All}}function parseJustify(value){if(value==null)return Justify.FlexStart;switch(value.toLowerCase()){case"flex-start":return Justify.FlexStart;case"center":return Justify.Center;case"flex-end":return Justify.FlexEnd;case"space-between":return Justify.SpaceBetween;case"space-around":return Justify.SpaceAround;case"space-evenly":return Justify.SpaceEvenly;default:return Justify.FlexStart}}function parseLogLevel(value){if(value==null)return LogLevel.Info;switch(value.toLowerCase()){case"error":return LogLevel.Error;case"warn":return LogLevel.Warn;case"info":return LogLevel.Info;case"debug":return LogLevel.Debug;case"verbose":return LogLevel.Verbose;case"fatal":return LogLevel.Fatal;default:return LogLevel.Info}}function parseMeasureMode(value){if(value==null)return MeasureMode.Undefined;switch(value.toLowerCase()){case"undefined":return MeasureMode.Undefined;case"exactly":return MeasureMode.Exactly;case"at-most":return MeasureMode.AtMost;default:return MeasureMode.Undefined}}function parseOverflow(value){if(value==null)return Overflow.Visible;switch(value.toLowerCase()){case"visible":return Overflow.Visible;case"hidden":return Overflow.Hidden;case"scroll":return Overflow.Scroll;default:return Overflow.Visible}}function parsePositionType(value){if(value==null)return PositionType.Relative;switch(value.toLowerCase()){case"static":return PositionType.Static;case"relative":return PositionType.Relative;case"absolute":return PositionType.Absolute;default:return PositionType.Static}}function parseUnit(value){if(value==null)return Unit.Point;switch(value.toLowerCase()){case"undefined":return Unit.Undefined;case"point":return Unit.Point;case"percent":return Unit.Percent;case"auto":return Unit.Auto;default:return Unit.Point}}function parseWrap(value){if(value==null)return Wrap.NoWrap;switch(value.toLowerCase()){case"no-wrap":return Wrap.NoWrap;case"wrap":return Wrap.Wrap;case"wrap-reverse":return Wrap.WrapReverse;default:return Wrap.NoWrap}}class SelectionAnchor{renderable;relativeX;relativeY;constructor(renderable,absoluteX,absoluteY){this.renderable=renderable,this.relativeX=absoluteX-this.renderable.x,this.relativeY=absoluteY-this.renderable.y}get x(){return this.renderable.x+this.relativeX}get y(){return this.renderable.y+this.relativeY}}class Selection{_anchor;_focus;_selectedRenderables=[];_touchedRenderables=[];_isActive=!0;_isDragging=!0;_isStart=!1;constructor(anchorRenderable,anchor,focus){this._anchor=new SelectionAnchor(anchorRenderable,anchor.x,anchor.y),this._focus={...focus}}get isStart(){return this._isStart}set isStart(value){this._isStart=value}get anchor(){return{x:this._anchor.x,y:this._anchor.y}}get focus(){return{...this._focus}}set focus(value){this._focus={...value}}get isActive(){return this._isActive}set isActive(value){this._isActive=value}get isDragging(){return this._isDragging}set isDragging(value){this._isDragging=value}get bounds(){let minX=Math.min(this._anchor.x,this._focus.x),maxX=Math.max(this._anchor.x,this._focus.x),minY=Math.min(this._anchor.y,this._focus.y),maxY=Math.max(this._anchor.y,this._focus.y),width=maxX-minX+1,height2=maxY-minY+1;return{x:minX,y:minY,width,height:height2}}updateSelectedRenderables(selectedRenderables){this._selectedRenderables=selectedRenderables}get selectedRenderables(){return this._selectedRenderables}updateTouchedRenderables(touchedRenderables){this._touchedRenderables=touchedRenderables}get touchedRenderables(){return this._touchedRenderables}getSelectedText(){return this._selectedRenderables.sort((a,b2)=>{let aY=a.y,bY=b2.y;if(aY!==bY)return aY-bY;return a.x-b2.x}).filter((renderable)=>!renderable.isDestroyed).map((renderable)=>renderable.getSelectedText()).filter((text)=>text).join(`
|
|
1439
1438
|
`)}}function convertGlobalToLocalSelection(globalSelection,localX,localY){if(!globalSelection?.isActive)return null;return{anchorX:globalSelection.anchor.x-localX,anchorY:globalSelection.anchor.y-localY,focusX:globalSelection.focus.x-localX,focusY:globalSelection.focus.y-localY,isActive:!0}}class ASCIIFontSelectionHelper{getText;getFont;localSelection=null;constructor(getText,getFont){this.getText=getText,this.getFont=getFont}hasSelection(){return this.localSelection!==null}getSelection(){return this.localSelection}shouldStartSelection(localX,localY,width,height2){if(localX<0||localX>=width||localY<0||localY>=height2)return!1;let text=this.getText(),font=this.getFont(),charIndex=coordinateToCharacterIndex(localX,text,font);return charIndex>=0&&charIndex<=text.length}onLocalSelectionChanged(localSelection,width,height2){let previousSelection=this.localSelection;if(!localSelection?.isActive)return this.localSelection=null,previousSelection!==null;let text=this.getText(),font=this.getFont(),selStart={x:localSelection.anchorX,y:localSelection.anchorY},selEnd={x:localSelection.focusX,y:localSelection.focusY};if(height2-1<selStart.y||0>selEnd.y)return this.localSelection=null,previousSelection!==null;let startCharIndex=0,endCharIndex=text.length;if(selStart.y>height2-1)return this.localSelection=null,previousSelection!==null;else if(selStart.y>=0&&selStart.y<=height2-1){if(selStart.x>0)startCharIndex=coordinateToCharacterIndex(selStart.x,text,font)}if(selEnd.y<0)return this.localSelection=null,previousSelection!==null;else if(selEnd.y>=0&&selEnd.y<=height2-1)if(selEnd.x>=0)endCharIndex=coordinateToCharacterIndex(selEnd.x,text,font);else endCharIndex=0;if(startCharIndex<endCharIndex&&startCharIndex>=0&&endCharIndex<=text.length)this.localSelection={start:startCharIndex,end:endCharIndex};else this.localSelection=null;return previousSelection?.start!==this.localSelection?.start||previousSelection?.end!==this.localSelection?.end}}function singleton(key,factory){let bag=globalThis[singletonCacheSymbol]??={};if(!(key in bag))bag[key]=factory();return bag[key]}function destroySingleton(key){let bag=globalThis[singletonCacheSymbol];if(bag&&key in bag)delete bag[key]}function hasSingleton(key){let bag=globalThis[singletonCacheSymbol];return bag&&key in bag}function registerEnvVar(config){let existing=envRegistry[config.name];if(existing){if(existing.description!==config.description||existing.type!==config.type||existing.default!==config.default)throw Error(`Environment variable "${config.name}" is already registered with different configuration. Existing: ${JSON.stringify(existing)}, New: ${JSON.stringify(config)}`);return}envRegistry[config.name]=config}function normalizeBoolean(value){let lowerValue=value.toLowerCase();return["true","1","on","yes"].includes(lowerValue)}function parseEnvValue(config){let envValue=process.env[config.name];if(envValue===void 0&&config.default!==void 0)return config.default;if(envValue===void 0)throw Error(`Required environment variable ${config.name} is not set. ${config.description}`);switch(config.type){case"boolean":return typeof envValue==="boolean"?envValue:normalizeBoolean(envValue);case"number":let numValue=Number(envValue);if(isNaN(numValue))throw Error(`Environment variable ${config.name} must be a valid number, got: ${envValue}`);return numValue;case"string":default:return envValue}}class EnvStore{parsedValues=new Map;get(key){if(this.parsedValues.has(key))return this.parsedValues.get(key);if(!(key in envRegistry))throw Error(`Environment variable ${key} is not registered.`);try{let value=parseEnvValue(envRegistry[key]);return this.parsedValues.set(key,value),value}catch(error2){throw Error(`Failed to parse env var ${key}: ${error2 instanceof Error?error2.message:String(error2)}`)}}has(key){return key in envRegistry}clearCache(){this.parsedValues.clear()}}function clearEnvCache(){envStore.clearCache()}function generateEnvMarkdown(){let configs=Object.values(envRegistry);if(configs.length===0)return`# Environment Variables
|
|
@@ -1881,9 +1880,7 @@ To install use this command:
|
|
|
1881
1880
|
|
|
1882
1881
|
$ bun add react-devtools-core@7 -d
|
|
1883
1882
|
`.trim()+`
|
|
1884
|
-
`);else throw error2}reconciler.injectIntoDevTools();_r=reconciler,flushSync=_r.flushSyncFromReconciler??_r.flushSync});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)},[])}function renderPluginFailurePlaceholder(registry,pluginFailurePlaceholder,failure,pluginId,slot){if(!pluginFailurePlaceholder)return null;try{return pluginFailurePlaceholder(failure)}catch(error2){return registry.reportPluginError({pluginId,slot,phase:"error_placeholder",source:"react",error:error2}),null}}var import_react5,import_react6,import_react7,import_react8,import_react9,import_react10,import_react11,import_react12,useKeyboard=(handler,options={release:!1})=>{let{keyHandler}=useAppContext(),stableHandler=useEffectEvent(handler);import_react5.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])},useRenderer=()=>{let{renderer}=useAppContext();if(!renderer)throw Error("Renderer not found.");return renderer},PluginErrorBoundary;var init_react=__esm(async()=>{init_chunk_2mx7fq49();await __promiseAll([init_chunk_kxd698dk(),init_core(),init_core(),init_core()]);import_react5=__toESM(require_react_development(),1),import_react6=__toESM(require_react_development(),1),import_react7=__toESM(require_react_development(),1),import_react8=__toESM(require_react_development(),1),import_react9=__toESM(require_react_development(),1),import_react10=__toESM(require_react_development(),1),import_react11=__toESM(require_react_development(),1),import_react12=__toESM(require_react_development(),1);PluginErrorBoundary=class PluginErrorBoundary extends import_react10.default.Component{constructor(props){super(props);this.state={failure:null}}componentDidCatch(error2){let failure=this.props.registry.reportPluginError({pluginId:this.props.pluginId,slot:this.props.slotName,phase:"render",source:"react",error:error2});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}};extend3({"time-to-first-draw":TimeToFirstDrawRenderable})});
|
|
1885
|
-
FROM tasks WHERE status NOT IN ('cancelled')
|
|
1886
|
-
ORDER BY priority DESC, seq ASC`,sql`SELECT agent_name, project_id, role FROM agent_projects`]);return{orgs:orgRows.map(mapOrg),projects:projRows.map(mapProject2),boards:boardRows.map(mapBoard2),tasks:taskRows.map(mapTask2),agentProjects:apRows.map(mapAgentProject)}}async function subscribe(onEvent){let{followRuntimeEvents:followRuntimeEvents2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events)),handle=await followRuntimeEvents2({},(event)=>{onEvent(event.kind,{id:event.id,agent:event.agent,team:event.team,text:event.text,subject:event.subject,data:event.data})});return{stop:()=>handle.stop()}}async function loadExecutors(){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return(await(await getConnection2())`
|
|
1883
|
+
`);else throw error2}reconciler.injectIntoDevTools();_r=reconciler,flushSync=_r.flushSyncFromReconciler??_r.flushSync});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)},[])}function renderPluginFailurePlaceholder(registry,pluginFailurePlaceholder,failure,pluginId,slot){if(!pluginFailurePlaceholder)return null;try{return pluginFailurePlaceholder(failure)}catch(error2){return registry.reportPluginError({pluginId,slot,phase:"error_placeholder",source:"react",error:error2}),null}}var import_react5,import_react6,import_react7,import_react8,import_react9,import_react10,import_react11,import_react12,useKeyboard=(handler,options={release:!1})=>{let{keyHandler}=useAppContext(),stableHandler=useEffectEvent(handler);import_react5.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])},useRenderer=()=>{let{renderer}=useAppContext();if(!renderer)throw Error("Renderer not found.");return renderer},PluginErrorBoundary;var init_react=__esm(async()=>{init_chunk_2mx7fq49();await __promiseAll([init_chunk_kxd698dk(),init_core(),init_core(),init_core()]);import_react5=__toESM(require_react_development(),1),import_react6=__toESM(require_react_development(),1),import_react7=__toESM(require_react_development(),1),import_react8=__toESM(require_react_development(),1),import_react9=__toESM(require_react_development(),1),import_react10=__toESM(require_react_development(),1),import_react11=__toESM(require_react_development(),1),import_react12=__toESM(require_react_development(),1);PluginErrorBoundary=class PluginErrorBoundary extends import_react10.default.Component{constructor(props){super(props);this.state={failure:null}}componentDidCatch(error2){let failure=this.props.registry.reportPluginError({pluginId:this.props.pluginId,slot:this.props.slotName,phase:"render",source:"react",error:error2});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}};extend3({"time-to-first-draw":TimeToFirstDrawRenderable})});var exports_db2={};__export(exports_db2,{loadExecutors:()=>loadExecutors,loadAssignments:()=>loadAssignments});async function loadExecutors(){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return(await(await getConnection2())`
|
|
1887
1884
|
SELECT e.id, e.agent_id, e.provider, e.transport, e.pid, e.tmux_session,
|
|
1888
1885
|
e.tmux_pane_id, e.state, e.metadata, e.started_at,
|
|
1889
1886
|
a.custom_name AS agent_name, a.role, a.team
|
|
@@ -1899,9 +1896,8 @@ $ bun add react-devtools-core@7 -d
|
|
|
1899
1896
|
WHERE a.executor_id = ANY(${executorIds})
|
|
1900
1897
|
AND a.ended_at IS NULL
|
|
1901
1898
|
ORDER BY a.started_at DESC
|
|
1902
|
-
`).map(mapAssignment)}function
|
|
1903
|
-
`)){if(!line)continue;let[sessName,winIdx,winName,winActive,winPanes,sessAttached,sessWindows]=line.split("|");if(!sessionMap.has(sessName))sessionMap.set(sessName,{name:sessName,attached:sessAttached==="1",windowCount:Number.parseInt(sessWindows,10)||0,windows:[]});sessionMap.get(sessName)?.windows.push({sessionName:sessName,index:Number.parseInt(winIdx,10)||0,name:winName,active:winActive==="1",paneCount:Number.parseInt(winPanes,10)||0})}return Array.from(sessionMap.values()).sort((a,b3)=>a.name.localeCompare(b3.name))}var init_db2=()=>{};import{execSync as execSync15}from"child_process";function execQuiet(cmd){try{return execSync15(cmd,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return""}}function parsePaneLine(parts){let[sessionName,winIdxStr,winName,winActive,winPanes,paneIdxStr,paneId,panePidStr,paneCmd,paneTitle,paneSize,sessAttached,sessWindows,sessCreated,paneDead]=parts;return{sessionName,winIdxStr,session:{name:sessionName,attached:sessAttached==="1",windowCount:Number.parseInt(sessWindows,10)||0,created:Number.parseInt(sessCreated,10)||0},window:{sessionName,index:Number.parseInt(winIdxStr,10)||0,name:winName,active:winActive==="1",paneCount:Number.parseInt(winPanes,10)||0},pane:{sessionName,windowIndex:Number.parseInt(winIdxStr,10)||0,paneIndex:Number.parseInt(paneIdxStr,10)||0,paneId,pid:Number.parseInt(panePidStr,10)||0,command:paneCmd,title:paneTitle,size:paneSize,isDead:paneDead==="1"}}}function getTmuxInventory(){let paneOutput=execQuiet("tmux list-panes -a -F '#{session_name}|#{window_index}|#{window_name}|#{window_active}|#{window_panes}|#{pane_index}|#{pane_id}|#{pane_pid}|#{pane_current_command}|#{pane_title}|#{pane_width}x#{pane_height}|#{session_attached}|#{session_windows}|#{session_created}|#{pane_dead}'");if(!paneOutput)return[];let sessionMap=new Map,windowMap=new Map;for(let line of paneOutput.split(`
|
|
1904
|
-
`)){if(!line)continue;let parts=line.split("|");if(parts.length<15)continue;let parsed=parsePaneLine(parts);if(!sessionMap.has(parsed.sessionName))sessionMap.set(parsed.sessionName,{...parsed.session,windows:[]});let winKey=`${parsed.sessionName}:${parsed.winIdxStr}`;if(!windowMap.has(winKey)){let win={...parsed.window,panes:[]};windowMap.set(winKey,win),sessionMap.get(parsed.sessionName)?.windows.push(win)}windowMap.get(winKey)?.panes.push(parsed.pane)}return Array.from(sessionMap.values()).sort((a,b3)=>a.name.localeCompare(b3.name))}function isPidAlive(pid){try{return process.kill(pid,0),!0}catch{return!1}}function allClaudePanes(sessions){return sessions.flatMap((s)=>s.windows.flatMap((w2)=>w2.panes)).filter((p)=>p.command==="claude"||p.title.includes("claude"))}function detectGaps(executors,sessions){let deadPidExecutors=executors.filter((e)=>e.pid!=null&&!isPidAlive(e.pid)),executorPaneIds=new Set(executors.map((e)=>e.tmuxPaneId).filter(Boolean)),claudePanes=allClaudePanes(sessions),orphanPanes=claudePanes.filter((p)=>!executorPaneIds.has(p.paneId)),linkedCount=executors.filter((e)=>e.tmuxPaneId&&!deadPidExecutors.some((d2)=>d2.id===e.id)).length,deadPaneCount=sessions.flatMap((s)=>s.windows.flatMap((w2)=>w2.panes)).filter((p)=>p.isDead).length;return{deadPidExecutors,orphanPanes,linkedCount,totalExecutors:executors.length,totalClaudePanes:claudePanes.length,deadPaneCount}}async function collectDiagnostics(){let{loadExecutors:loadExecutors2,loadAssignments:loadAssignments2}=await Promise.resolve().then(() => (init_db2(),exports_db2)),sessions=getTmuxInventory(),executors=await loadExecutors2(),executorIds=executors.map((e)=>e.id),assignments=await loadAssignments2(executorIds),gaps=detectGaps(executors,sessions);return{sessions,executors,assignments,gaps,timestamp:Date.now()}}var init_diagnostics=()=>{};function buildTree(data){let orgNodes=[];for(let org of data.orgs){let projectNodes=data.projects.filter((p)=>p.orgId===org.id).map((proj)=>{let boardNodes=data.boards.filter((b3)=>b3.projectId===proj.id).map((board)=>{let columnNodes=(board.columns||[]).sort((a,b3)=>a.position-b3.position).map((col)=>{let colTasks=data.tasks.filter((t2)=>t2.boardId===board.id&&t2.columnId===col.id),taskNodes=colTasks.map((task)=>({id:task.id,type:"task",label:`#${task.seq} ${task.title}`,depth:4,expanded:!1,children:[],data:task,activePanes:0}));return{id:col.id,type:"column",label:`${col.label} (${colTasks.length})`,depth:3,expanded:!1,children:taskNodes,data:col,activePanes:0}});return{id:board.id,type:"board",label:board.name,depth:2,expanded:!1,children:columnNodes,data:board,activePanes:0}});return{id:proj.id,type:"project",label:proj.name,depth:1,expanded:!1,children:boardNodes,data:proj,activePanes:0}});orgNodes.push({id:org.id,type:"org",label:org.name,depth:0,expanded:!0,children:projectNodes,data:org,activePanes:0})}return orgNodes}function flattenTree(nodes){let result=[];function walk(node,depth){if(result.push({node,depth,visible:!0}),node.expanded)for(let child of node.children)walk(child,depth+1)}for(let node of nodes)walk(node,0);return result}function toggleNode(nodes,id){return nodes.map((node)=>{if(node.id===id)return{...node,expanded:!node.expanded};return{...node,children:toggleNode(node.children,id)}})}function applyActivity(nodes,activity){return nodes.map((node)=>{let act=activity.get(node.id),updated={...node,activePanes:act?.panes??0,agentState:act?.state,children:applyActivity(node.children,activity)};if(updated.children.some((c)=>c.activePanes>0)&&updated.activePanes===0)updated.activePanes=updated.children.reduce((sum,c)=>sum+c.activePanes,0);return updated})}var import_jsx_dev_runtime2;var init_jsx_dev_runtime=__esm(()=>{import_jsx_dev_runtime2=__toESM(require_react_jsx_dev_runtime_development(),1)});function stateColor(state){return STATE_COLORS[state]??palette.textMuted}function executorDisplayName(exec3){let name=exec3.agentName?`${exec3.agentName}${exec3.team?`@${exec3.team}`:""}`:exec3.agentId;return exec3.role?`${name} (${exec3.role})`:name}function metaRow(exec3){let hasTmux2=!!exec3.tmuxPaneId,isApi=exec3.transport==="api";return{id:`meta:${exec3.id}`,depth:1,label:hasTmux2?`${exec3.tmuxSession??"?"}:${exec3.tmuxPaneId}`:isApi?"api (no tmux)":"tmux: not linked",color:hasTmux2?palette.emerald:isApi?palette.textDim:palette.error,detail:exec3.pid!=null?`pid:${exec3.pid}`:"",detailColor:palette.textMuted,isOrphan:!hasTmux2&&!isApi}}function assignmentRow(exec3,a){let taskLabel=a.taskTitle??a.taskId??"unknown",wishLabel=a.wishSlug?` [${a.wishSlug}]`:"";return{id:`assign:${exec3.id}`,depth:1,label:`\u2192 ${taskLabel}${wishLabel}`,color:palette.purple,detail:a.groupNumber!=null?`grp:${a.groupNumber}`:"",detailColor:palette.textMuted,isOrphan:!1}}function executorToRows(exec3,assignments,isDead){let rows=[{id:`exec:${exec3.id}`,depth:0,label:executorDisplayName(exec3),color:isDead?palette.error:stateColor(exec3.state),detail:isDead?`DEAD pid:${exec3.pid}`:`${exec3.state} ${exec3.provider}`,detailColor:isDead?palette.error:palette.textMuted,isOrphan:isDead},metaRow(exec3)],active=assignments.find((a)=>a.executorId===exec3.id);if(active)rows.push(assignmentRow(exec3,active));return rows}function flattenExecutors(executors,assignments,gaps){let deadIds=new Set(gaps.deadPidExecutors.map((e)=>e.id)),byProvider=new Map;for(let exec3 of executors){let key=exec3.provider;if(!byProvider.has(key))byProvider.set(key,[]);byProvider.get(key)?.push(exec3)}let rows=[];for(let[provider,group]of byProvider){rows.push({id:`provider:${provider}`,depth:0,label:`\u2500\u2500 ${provider} (${group.length}) \u2500\u2500`,color:palette.cyan,detail:"",detailColor:palette.textMuted,isOrphan:!1});for(let exec3 of group)for(let row of executorToRows(exec3,assignments,deadIds.has(exec3.id)))rows.push({...row,depth:row.depth+1})}if(gaps.orphanPanes.length>0){rows.push({id:"orphan-header",depth:0,label:`\u2500\u2500 Orphan Panes (${gaps.orphanPanes.length}) \u2500\u2500`,color:palette.warning,detail:"",detailColor:palette.textMuted,isOrphan:!1});for(let pane of gaps.orphanPanes)rows.push({id:`orphan:${pane.paneId}`,depth:1,label:`${pane.sessionName}:${pane.windowIndex}.${pane.paneIndex}`,color:palette.error,detail:`pid:${pane.pid} [${pane.title}]`,detailColor:palette.textMuted,isOrphan:!0})}return rows}function ClaudeView({executors,assignments,gaps,selectedIndex}){let rows=import_react13.useMemo(()=>flattenExecutors(executors,assignments,gaps),[executors,assignments,gaps]);return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",width:"100%",height:"100%",children:[import_jsx_dev_runtime2.jsxDEV("box",{height:1,paddingX:1,backgroundColor:palette.bgLighter,children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.emerald,children:[gaps.linkedCount," linked"]},void 0,!0,void 0,this),gaps.deadPidExecutors.length>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ",gaps.deadPidExecutors.length," dead"]},void 0,!0,void 0,this):null,gaps.orphanPanes.length>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.warning,children:[" ",gaps.orphanPanes.length," unmapped"]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("scrollbox",{focused:!0,height:"100%",style:{scrollbarOptions:{showArrows:!1,trackOptions:{foregroundColor:palette.scrollThumb,backgroundColor:palette.scrollTrack}}},children:rows.map((row,i2)=>{let indent=" ".repeat(row.depth),icon=row.depth===0?row.isOrphan?"\u2718":"\u2713":"\u2514";return import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",backgroundColor:i2===selectedIndex?palette.violet:void 0,children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:indent},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:row.color,children:[icon," ",row.label]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:row.detailColor,children:[" ",row.detail]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},row.id,!1,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function getClaudeRowCount(executors,assignments,gaps){let count=new Set(executors.map((e)=>e.provider)).size;for(let exec3 of executors)if(count+=2,assignments.some((a)=>a.executorId===exec3.id))count++;if(gaps.orphanPanes.length>0)count+=1+gaps.orphanPanes.length;return count}var import_react13,STATE_COLORS;var init_ClaudeView=__esm(()=>{init_theme2();init_jsx_dev_runtime();import_react13=__toESM(require_react_development(),1),STATE_COLORS={working:palette.emerald,idle:palette.textDim,running:palette.cyan,spawning:palette.warning,permission:palette.warning,question:palette.warning,error:palette.error}});function tabBadge(tab,gaps){if(tab==="claude"){let total=(gaps?.orphanProcesses??0)+(gaps?.orphanPanes??0);return total>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ",total]},void 0,!0,void 0,this):null}if(tab==="tmux"){let dead=gaps?.deadPanes??0;return dead>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ",dead,"\\u2620"]},void 0,!0,void 0,this):null}return null}function TabBar({activeTab,focused,gaps}){return import_jsx_dev_runtime2.jsxDEV("box",{height:1,flexDirection:"row",width:"100%",backgroundColor:palette.bgLight,children:TAB_ORDER.map((tab)=>{let isActive=tab===activeTab,bg2=isActive?palette.violet:palette.bgLight,fg2=isActive?"#ffffff":focused?palette.textDim:palette.textMuted;return import_jsx_dev_runtime2.jsxDEV("box",{backgroundColor:bg2,paddingX:1,children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:fg2,children:[isActive&&focused?">":" ",TAB_LABELS[tab]]},void 0,!0,void 0,this),tabBadge(tab,gaps)]},void 0,!0,void 0,this)},tab,!1,void 0,this)})},void 0,!1,void 0,this)}var TAB_ORDER,TAB_LABELS;var init_TabBar=__esm(()=>{init_theme2();init_jsx_dev_runtime();TAB_ORDER=["tmux","claude"],TAB_LABELS={projects:"Projects",tmux:"Sessions",claude:"Executors"}});function toPaneRow(pane,sessionName,windowIndex){let isClaude=pane.command==="claude"||pane.title.includes("claude"),color=pane.isDead?palette.textMuted:isClaude?palette.cyan:palette.textDim;return{id:`p:${pane.paneId}`,depth:2,label:pane.isDead?`${pane.paneId} [DEAD]`:`${pane.paneId} [${pane.command}]`,color,detail:`pid:${pane.pid} ${pane.size}`,detailColor:palette.textMuted,type:"pane",sessionName,windowIndex,isClaude,isDead:pane.isDead}}function flattenSessions(sessions){return sessions.flatMap((session)=>{let sessionRow={id:`s:${session.name}`,depth:0,label:session.name,color:session.attached?palette.emerald:palette.textDim,detail:`${session.windowCount}w ${session.attached?"(attached)":""}`,detailColor:session.attached?palette.emerald:palette.textMuted,type:"session",sessionName:session.name,isClaude:!1,isDead:!1},windowRows=session.windows.flatMap((window2)=>{let deadInWindow=window2.panes.filter((p)=>p.isDead).length,winRow={id:`w:${session.name}:${window2.index}`,depth:1,label:`${window2.index}:${window2.name}`,color:window2.active?palette.cyan:palette.text,detail:`${window2.paneCount}p${deadInWindow>0?` ${deadInWindow}\u2620`:""}${window2.active?" *":""}`,detailColor:window2.active?palette.cyan:palette.textMuted,type:"window",sessionName:session.name,windowIndex:window2.index,isClaude:!1,isDead:!1},paneRows=window2.panes.map((pane)=>toPaneRow(pane,session.name,window2.index));return[winRow,...paneRows]});return[sessionRow,...windowRows]})}function TmuxView({sessions,selectedIndex}){let rows=import_react14.useMemo(()=>flattenSessions(sessions),[sessions]),totalPanes=sessions.reduce((sum,s)=>sum+s.windows.reduce((ws,w2)=>ws+w2.panes.length,0),0),deadPanes=sessions.reduce((sum,s)=>sum+s.windows.reduce((ws,w2)=>ws+w2.panes.filter((p)=>p.isDead).length,0),0);return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",width:"100%",height:"100%",children:[import_jsx_dev_runtime2.jsxDEV("box",{height:1,paddingX:1,backgroundColor:palette.bgLighter,children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:[sessions.length,"s ",sessions.reduce((s,x2)=>s+x2.windowCount,0),"w ",totalPanes,"p"]},void 0,!0,void 0,this),deadPanes>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ",deadPanes," dead"]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("scrollbox",{focused:!0,height:"100%",style:{scrollbarOptions:{showArrows:!1,trackOptions:{foregroundColor:palette.scrollThumb,backgroundColor:palette.scrollTrack}}},children:rows.map((row,i2)=>{let indent=" ".repeat(row.depth),icon=row.type==="session"?"\u25C8":row.type==="window"?"\u25A1":row.isDead?"\u2718":"\u2500";return import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",backgroundColor:i2===selectedIndex?palette.violet:void 0,children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:indent},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:row.color,children:[icon," ",row.label]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:row.detailColor,children:[" ",row.detail]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},row.id,!1,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function getTmuxRowCount(sessions){let count=0;for(let s of sessions){count++;for(let w2 of s.windows)count++,count+=w2.panes.length}return count}function getTmuxRowTarget(sessions,index){let row=flattenSessions(sessions)[index];if(!row)return null;return{sessionName:row.sessionName,windowIndex:row.windowIndex}}var import_react14;var init_TmuxView=__esm(()=>{init_theme2();init_jsx_dev_runtime();import_react14=__toESM(require_react_development(),1)});function getNodeIcon(node){switch(node.type){case"org":return icons.org;case"project":return node.expanded?icons.projectOpen:icons.project;case"board":return node.expanded?icons.boardOpen:icons.board;case"column":return icons.column;case"task":if(node.activePanes>0)return icons.taskActive;if(node.data.status==="done")return icons.taskDone;return icons.task;default:return" "}}function getNodeColor(node){switch(node.type){case"org":return palette.purple;case"project":return node.activePanes>0?palette.emerald:palette.textDim;case"board":return palette.violet;case"column":return palette.textMuted;case"task":if(node.activePanes>0)return palette.cyan;if(node.data.status==="done")return palette.emerald;return palette.text;default:return palette.text}}var import_react15,TreeNodeRow;var init_TreeNode=__esm(()=>{init_theme2();init_jsx_dev_runtime();import_react15=__toESM(require_react_development(),1),TreeNodeRow=import_react15.memo(function({node,selected,onSelect,onToggle}){let indent=" ".repeat(node.depth),hasChildren=node.children.length>0,expandIcon=hasChildren?node.expanded?icons.expanded:icons.collapsed:" ",icon=getNodeIcon(node),color=getNodeColor(node),activeIndicator=node.activePanes>0?` ${icons.agent}${node.activePanes}`:"";return import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",backgroundColor:selected?palette.violet:void 0,onMouseDown:()=>{if(onSelect(node.id),hasChildren)onToggle(node.id)},children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:[indent,expandIcon," "]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:color,children:[icon," "]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:selected?"#ffffff":palette.text,children:node.label},void 0,!1,void 0,this),activeIndicator?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.cyan,children:activeIndicator},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)})});function Nav({tree,onTreeChange,onProjectSelect,onTmuxSessionSelect}){let[activeTab,setActiveTab]=import_react17.useState("tmux"),[tabBarFocused,setTabBarFocused]=import_react17.useState(!1),[diagnostics,setDiagnostics]=import_react17.useState(null),[projectIndex,setProjectIndex]=import_react17.useState(0),[tmuxIndex,setTmuxIndex]=import_react17.useState(0),[claudeIndex,setClaudeIndex]=import_react17.useState(0),flatNodes=import_react17.useMemo(()=>flattenTree(tree),[tree]),diagTimer=import_react17.useRef(null);import_react17.useEffect(()=>{let active=!0;async function refresh(){try{let snap=await collectDiagnostics();if(active)setDiagnostics(snap)}catch(err){console.error("TUI: diagnostics failed:",err)}}return refresh(),diagTimer.current=setInterval(refresh,2000),()=>{if(active=!1,diagTimer.current)clearInterval(diagTimer.current)}},[]);let getRowCount=import_react17.useCallback(()=>{switch(activeTab){case"projects":return flatNodes.length;case"tmux":return diagnostics?getTmuxRowCount(diagnostics.sessions):0;case"claude":return diagnostics?getClaudeRowCount(diagnostics.executors,diagnostics.assignments,diagnostics.gaps):0}},[activeTab,flatNodes,diagnostics]),getSelectedIndex=import_react17.useCallback(()=>{switch(activeTab){case"projects":return projectIndex;case"tmux":return tmuxIndex;case"claude":return claudeIndex}},[activeTab,projectIndex,tmuxIndex,claudeIndex]),setSelectedIndex=import_react17.useCallback((idx)=>{switch(activeTab){case"projects":setProjectIndex(idx);break;case"tmux":setTmuxIndex(idx);break;case"claude":setClaudeIndex(idx);break}},[activeTab]);import_react17.useEffect(()=>{if(activeTab!=="projects"||tabBarFocused)return;let current=flatNodes[projectIndex]?.node;if(!current||current.type!=="project")return;let proj=current.data;if(proj.tmuxSession)onProjectSelect(proj.id,proj.tmuxSession)},[activeTab,tabBarFocused,projectIndex,flatNodes,onProjectSelect]);let handleProjectSelect=import_react17.useCallback((id)=>{let idx=flatNodes.findIndex((n)=>n.node.id===id);if(idx>=0)setProjectIndex(idx)},[flatNodes]),handleToggle=import_react17.useCallback((id)=>{onTreeChange(toggleNode(tree,id))},[tree,onTreeChange]),handleEnter=import_react17.useCallback(()=>{if(activeTab==="projects"){let current=flatNodes[projectIndex]?.node;if(!current)return;if(current.type==="project"){let proj=current.data;onProjectSelect(proj.id,proj.tmuxSession)}else if(current.children.length>0)handleToggle(current.id)}else if(activeTab==="tmux"&&diagnostics&&onTmuxSessionSelect){let target=getTmuxRowTarget(diagnostics.sessions,tmuxIndex);if(target)onTmuxSessionSelect(target.sessionName,target.windowIndex)}},[activeTab,flatNodes,projectIndex,onProjectSelect,handleToggle,diagnostics,tmuxIndex,onTmuxSessionSelect]),handleTabBarKey=import_react17.useCallback((keyName2)=>{if(keyName2==="left"||keyName2==="h"){let idx=(TAB_ORDER.indexOf(activeTab)-1+TAB_ORDER.length)%TAB_ORDER.length;return setActiveTab(TAB_ORDER[idx]),!0}if(keyName2==="right"||keyName2==="l"){let idx=(TAB_ORDER.indexOf(activeTab)+1)%TAB_ORDER.length;return setActiveTab(TAB_ORDER[idx]),!0}if(keyName2==="down"||keyName2==="j")return setTabBarFocused(!1),setSelectedIndex(0),!0;return!1},[activeTab,setSelectedIndex]),handleVerticalNav=import_react17.useCallback((keyName2,selectedIdx,rowCount)=>{if(rowCount===0)return;if(keyName2==="up"||keyName2==="k")setSelectedIndex(selectedIdx===0?rowCount-1:selectedIdx-1);else if(keyName2==="down"||keyName2==="j")setSelectedIndex(selectedIdx>=rowCount-1?0:selectedIdx+1)},[setSelectedIndex]),handleTreeExpand=import_react17.useCallback((keyName2,selectedIdx)=>{if(activeTab!=="projects")return;let node=flatNodes[selectedIdx]?.node;if(!node)return;if((keyName2==="right"||keyName2==="l")&&node.children.length>0&&!node.expanded)handleToggle(node.id);else if((keyName2==="left"||keyName2==="h")&&node.expanded)handleToggle(node.id)},[activeTab,flatNodes,handleToggle]),handleListKey=import_react17.useCallback((keyName2,selectedIdx,rowCount)=>{if(keyName2==="enter"||keyName2==="return")handleEnter();else if(keyName2==="up"||keyName2==="k"||keyName2==="down"||keyName2==="j")handleVerticalNav(keyName2,selectedIdx,rowCount);else handleTreeExpand(keyName2,selectedIdx)},[handleEnter,handleVerticalNav,handleTreeExpand]);useKeyboard((key)=>{if(tabBarFocused){handleTabBarKey(key.name);return}handleListKey(key.name,getSelectedIndex(),getRowCount())});let gapCounts=diagnostics?{orphanProcesses:diagnostics.gaps.deadPidExecutors.length,orphanPanes:diagnostics.gaps.orphanPanes.length,deadPanes:diagnostics.gaps.deadPaneCount}:void 0;return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",width:"100%",height:"100%",backgroundColor:palette.bg,children:[import_jsx_dev_runtime2.jsxDEV(TabBar,{activeTab,focused:tabBarFocused,gaps:gapCounts},void 0,!1,void 0,this),activeTab==="projects"&&import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",flexGrow:1,children:import_jsx_dev_runtime2.jsxDEV("scrollbox",{focused:!0,height:"100%",style:{scrollbarOptions:{showArrows:!1,trackOptions:{foregroundColor:palette.scrollThumb,backgroundColor:palette.scrollTrack}}},children:flatNodes.map((flat,i2)=>import_jsx_dev_runtime2.jsxDEV(TreeNodeRow,{node:flat.node,selected:!tabBarFocused&&i2===projectIndex,onSelect:handleProjectSelect,onToggle:handleToggle},flat.node.id,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this),activeTab==="tmux"&&diagnostics&&import_jsx_dev_runtime2.jsxDEV(TmuxView,{sessions:diagnostics.sessions,selectedIndex:tabBarFocused?-1:tmuxIndex},void 0,!1,void 0,this),activeTab==="claude"&&diagnostics&&import_jsx_dev_runtime2.jsxDEV(ClaudeView,{executors:diagnostics.executors,assignments:diagnostics.assignments,gaps:diagnostics.gaps,selectedIndex:tabBarFocused?-1:claudeIndex},void 0,!1,void 0,this),(activeTab==="tmux"||activeTab==="claude")&&!diagnostics&&import_jsx_dev_runtime2.jsxDEV("box",{flexGrow:1,justifyContent:"center",alignItems:"center",children:import_jsx_dev_runtime2.jsxDEV("text",{fg:palette.textDim,children:"Collecting..."},void 0,!1,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("box",{height:1,paddingX:1,backgroundColor:palette.bgLight,children:import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:tabBarFocused?"\u2190\u2192:tab \u2193:tree":"\u2191\u2193:nav Enter:select"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var import_react17;var init_Nav=__esm(async()=>{init_diagnostics();init_theme2();init_ClaudeView();init_TabBar();init_TmuxView();init_TreeNode();init_jsx_dev_runtime();await init_react();import_react17=__toESM(require_react_development(),1)});function App({rightPane}){let renderer=useRenderer(),[tree,setTree]=import_react19.useState([]),[loading,setLoading]=import_react19.useState(!0),[error2,setError]=import_react19.useState(null),[currentProject,setCurrentProject]=import_react19.useState(null),dataRef=import_react19.useRef(null),subRef=import_react19.useRef(null);useKeyboard((key)=>{if(key.name==="q"||key.ctrl&&key.name==="c")renderer.destroy(),cleanup()}),import_react19.useEffect(()=>{let cancelled=!1,onEvent=async()=>{try{let freshData=await loadAll2();if(cancelled)return;dataRef.current=freshData,setTree((prev)=>mergeExpandedState(prev,buildTree(freshData)))}catch(err){console.error("TUI: data refresh failed:",err)}};async function boot(){let data=await loadAll2();if(cancelled)return;dataRef.current=data,setTree(buildTree(data)),setLoading(!1);let sub=await subscribe(onEvent);if(cancelled)return void sub.stop();subRef.current=sub}return boot().catch((err)=>{if(cancelled)return;setError(err instanceof Error?err.message:String(err)),setLoading(!1)}),()=>{cancelled=!0,subRef.current?.stop(),subRef.current=null}},[]);let executorsRef=import_react19.useRef([]),assignmentsRef=import_react19.useRef([]);import_react19.useEffect(()=>{let active=!0;async function refreshActivity(){if(!dataRef.current)return;let activity=await fetchMergedActivity(dataRef.current,executorsRef,assignmentsRef);if(active)setTree((prev)=>applyActivity(prev,activity))}let timer2=setInterval(refreshActivity,1000);return()=>{active=!1,clearInterval(timer2)}},[]);let handleTreeChange=import_react19.useCallback((newTree)=>{setTree(newTree)},[]),handleProjectSelect=import_react19.useCallback((projectId,tmuxSession)=>{if(!tmuxSession||!rightPane)return;if(currentProject===projectId)return;if(currentProject)switchRightPane(rightPane,tmuxSession);else attachProject(rightPane,tmuxSession);setCurrentProject(projectId)},[rightPane,currentProject]),handleTmuxSessionSelect=import_react19.useCallback((sessionName,windowIndex)=>{if(!rightPane)return;attachProjectWindow(rightPane,sessionName,windowIndex)},[rightPane]);if(loading)return import_jsx_dev_runtime2.jsxDEV("box",{width:"100%",height:"100%",backgroundColor:palette.bg,justifyContent:"center",alignItems:"center",children:import_jsx_dev_runtime2.jsxDEV("text",{fg:palette.purple,children:"Loading..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(error2)return import_jsx_dev_runtime2.jsxDEV("box",{width:"100%",height:"100%",backgroundColor:palette.bg,justifyContent:"center",alignItems:"center",children:import_jsx_dev_runtime2.jsxDEV("text",{fg:palette.error,children:error2},void 0,!1,void 0,this)},void 0,!1,void 0,this);return import_jsx_dev_runtime2.jsxDEV(Nav,{tree,onTreeChange:handleTreeChange,onProjectSelect:handleProjectSelect,onTmuxSessionSelect:handleTmuxSessionSelect},void 0,!1,void 0,this)}function mergeExpandedState(oldTree,newTree){let expandedIds=new Set;function collect(nodes){for(let n of nodes){if(n.expanded)expandedIds.add(n.id);collect(n.children)}}collect(oldTree);function apply(nodes){return nodes.map((n)=>({...n,expanded:expandedIds.has(n.id)||n.expanded,children:apply(n.children)}))}return apply(newTree)}function scanTmuxActivity(data){let result=new Map;for(let proj of data.projects){if(!proj.tmuxSession)continue;let windows=getActiveWork(proj.tmuxSession);for(let[taskId,act]of matchWorkToTasks(windows,data.tasks))result.set(taskId,act)}return result}async function fetchMergedActivity(data,executorsRef,assignmentsRef){try{let execs=await loadExecutors(),execIds=execs.map((e)=>e.id),assigns=execIds.length>0?await loadAssignments(execIds):[];executorsRef.current=execs,assignmentsRef.current=assigns;let activity=getExecutorActivity(execs,assigns);for(let[taskId,act]of scanTmuxActivity(data))if(!activity.has(taskId))activity.set(taskId,act);return activity}catch{return scanTmuxActivity(data)}}var import_react19;var init_app=__esm(async()=>{init_activity();init_db2();init_theme2();init_tmux2();init_jsx_dev_runtime();await __promiseAll([init_react(),init_Nav()]);import_react19=__toESM(require_react_development(),1)});var exports_render={};__export(exports_render,{renderNav:()=>renderNav});async function renderNav(){let rightPane=process.env.GENIE_TUI_RIGHT||void 0,renderer=await createCliRenderer({exitOnCtrlC:!1,useMouse:!0});createRoot(renderer).render(import_jsx_dev_runtime2.jsxDEV(App,{rightPane},void 0,!1,void 0,this))}var init_render=__esm(async()=>{init_jsx_dev_runtime();await __promiseAll([init_core(),init_react(),init_app()])});var exports_tui={};__export(exports_tui,{launchTui:()=>launchTui});async function launchTui(options={}){if(isInsideTuiSession()){let{renderNav:renderNav2}=await init_render().then(() => exports_render);await renderNav2();return}if(!hasTmux()){console.error("Error: tmux is required for genie tui");return}let{session,leftPane,rightPane}=createTuiSession(),bunPath=process.execPath||"bun",genieBin=process.argv[1]||"genie",{execSync:execSync16}=await import("child_process");if(options.dev)execSync16(`tmux send-keys -t '${leftPane}' "GENIE_TUI_PANE=left GENIE_TUI_RIGHT=${rightPane} bun --watch ${genieBin} tui" Enter`,{stdio:"ignore"});else execSync16(`tmux send-keys -t '${leftPane}' "GENIE_TUI_PANE=left GENIE_TUI_RIGHT=${rightPane} ${bunPath} ${genieBin} tui" Enter`,{stdio:"ignore"});attachTuiSession(),cleanup(session)}var init_tui=__esm(()=>{init_tmux2()});var import__=__toESM(require_commander(),1),{program,createCommand,createArgument,createOption,CommanderError,InvalidArgumentError,InvalidOptionArgumentError,Command,Argument,Option,Help}=import__.default;import{existsSync as existsSync3,unlinkSync as unlinkSync2}from"fs";import{homedir as homedir3}from"os";import{join as join3}from"path";var{$:$2}=globalThis.Bun;import{existsSync,unlinkSync}from"fs";import{homedir}from"os";import{join}from"path";var CLAUDE_DIR=join(homedir(),".claude"),CLAUDE_HOOKS_DIR=join(CLAUDE_DIR,"hooks"),CLAUDE_SETTINGS_FILE=join(CLAUDE_DIR,"settings.json"),GENIE_HOOK_SCRIPT_NAME="genie-bash-hook.sh";function getClaudeSettingsPath(){return CLAUDE_SETTINGS_FILE}function getGenieHookScriptPath(){return join(CLAUDE_HOOKS_DIR,GENIE_HOOK_SCRIPT_NAME)}function hookScriptExists(){return existsSync(getGenieHookScriptPath())}function removeHookScript(){let scriptPath=getGenieHookScriptPath();if(existsSync(scriptPath))unlinkSync(scriptPath)}function contractClaudePath(path){let home=homedir();if(path.startsWith(`${home}/`))return`~${path.slice(home.length)}`;if(path===home)return"~";return path}init_genie_config2();var{$}=globalThis.Bun;async function checkCommand(cmd){try{let cmdPath=(await $`which ${cmd}`.quiet().text()).trim();if(!cmdPath)return{exists:!1};let version;try{let firstLine=(await $`${cmd} --version`.quiet().text()).split(`
|
|
1899
|
+
`).map(mapAssignment)}function mapExecutor(row){let meta=row.metadata;return{id:String(row.id),agentId:String(row.agent_id),agentName:row.agent_name?String(row.agent_name):null,provider:String(row.provider),transport:String(row.transport),pid:row.pid!=null?Number(row.pid):null,tmuxSession:row.tmux_session?String(row.tmux_session):null,tmuxPaneId:row.tmux_pane_id?String(row.tmux_pane_id):null,state:String(row.state),metadata:typeof meta==="string"?JSON.parse(meta):meta??{},startedAt:row.started_at instanceof Date?row.started_at.toISOString():String(row.started_at),role:row.role?String(row.role):null,team:row.team?String(row.team):null}}function mapAssignment(row){return{id:String(row.id),executorId:String(row.executor_id),taskId:row.task_id?String(row.task_id):null,taskTitle:row.task_title?String(row.task_title):null,wishSlug:row.wish_slug?String(row.wish_slug):null,groupNumber:row.group_number!=null?Number(row.group_number):null,startedAt:row.started_at instanceof Date?row.started_at.toISOString():String(row.started_at)}}import{execSync as execSync14}from"child_process";function execQuiet(cmd){try{return execSync14(cmd,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return""}}function parsePaneLine(parts){let[sessionName,winIdxStr,winName,winActive,winPanes,paneIdxStr,paneId,panePidStr,paneCmd,paneTitle,paneSize,sessAttached,sessWindows,sessCreated,paneDead]=parts;return{sessionName,winIdxStr,session:{name:sessionName,attached:sessAttached==="1",windowCount:Number.parseInt(sessWindows,10)||0,created:Number.parseInt(sessCreated,10)||0},window:{sessionName,index:Number.parseInt(winIdxStr,10)||0,name:winName,active:winActive==="1",paneCount:Number.parseInt(winPanes,10)||0},pane:{sessionName,windowIndex:Number.parseInt(winIdxStr,10)||0,paneIndex:Number.parseInt(paneIdxStr,10)||0,paneId,pid:Number.parseInt(panePidStr,10)||0,command:paneCmd,title:paneTitle,size:paneSize,isDead:paneDead==="1"}}}function getTmuxInventory(){let paneOutput=execQuiet("tmux list-panes -a -F '#{session_name}|#{window_index}|#{window_name}|#{window_active}|#{window_panes}|#{pane_index}|#{pane_id}|#{pane_pid}|#{pane_current_command}|#{pane_title}|#{pane_width}x#{pane_height}|#{session_attached}|#{session_windows}|#{session_created}|#{pane_dead}'");if(!paneOutput)return[];let sessionMap=new Map,windowMap=new Map;for(let line of paneOutput.split(`
|
|
1900
|
+
`)){if(!line)continue;let parts=line.split("|");if(parts.length<15)continue;let parsed=parsePaneLine(parts);if(!sessionMap.has(parsed.sessionName))sessionMap.set(parsed.sessionName,{...parsed.session,windows:[]});let winKey=`${parsed.sessionName}:${parsed.winIdxStr}`;if(!windowMap.has(winKey)){let win={...parsed.window,panes:[]};windowMap.set(winKey,win),sessionMap.get(parsed.sessionName)?.windows.push(win)}windowMap.get(winKey)?.panes.push(parsed.pane)}return Array.from(sessionMap.values()).sort((a,b3)=>a.name.localeCompare(b3.name))}function isPidAlive(pid){try{return process.kill(pid,0),!0}catch{return!1}}function allClaudePanes(sessions){return sessions.flatMap((s)=>s.windows.flatMap((w2)=>w2.panes)).filter((p)=>p.command==="claude"||p.title.includes("claude"))}function detectGaps(executors,sessions){let deadPidExecutors=executors.filter((e)=>e.pid!=null&&!isPidAlive(e.pid)),executorPaneIds=new Set(executors.map((e)=>e.tmuxPaneId).filter(Boolean)),claudePanes=allClaudePanes(sessions),orphanPanes=claudePanes.filter((p)=>!executorPaneIds.has(p.paneId)),linkedCount=executors.filter((e)=>e.tmuxPaneId&&!deadPidExecutors.some((d2)=>d2.id===e.id)).length,deadPaneCount=sessions.flatMap((s)=>s.windows.flatMap((w2)=>w2.panes)).filter((p)=>p.isDead).length;return{deadPidExecutors,orphanPanes,linkedCount,totalExecutors:executors.length,totalClaudePanes:claudePanes.length,deadPaneCount}}async function collectDiagnostics(){let{loadExecutors:loadExecutors2,loadAssignments:loadAssignments2}=await Promise.resolve().then(() => exports_db2),sessions=getTmuxInventory(),executors=await loadExecutors2(),executorIds=executors.map((e)=>e.id),assignments=await loadAssignments2(executorIds),gaps=detectGaps(executors,sessions);return{sessions,executors,assignments,gaps,timestamp:Date.now()}}var init_diagnostics=()=>{};function buildSessionTree(snapshot){let executorByPaneId=new Map;for(let exec3 of snapshot.executors)if(exec3.tmuxPaneId)executorByPaneId.set(exec3.tmuxPaneId,exec3);return snapshot.sessions.map((session)=>sessionToNode(session,executorByPaneId))}function sessionToNode(session,executorMap){let claudePanes=session.windows.reduce((sum,w2)=>sum+w2.panes.filter((p)=>p.command==="claude"||p.title.includes("claude")).length,0);return{id:`session:${session.name}`,type:"session",label:session.name,depth:0,expanded:!0,children:session.windows.map((w2)=>windowToNode(session.name,w2,executorMap)),data:{attached:session.attached,windowCount:session.windowCount},activePanes:claudePanes,agentState:void 0}}function windowToNode(sessionName,window2,executorMap){let activePanes=window2.panes.filter((p)=>!p.isDead&&(p.command==="claude"||p.title.includes("claude"))).length;return{id:`window:${sessionName}:${window2.index}`,type:"window",label:window2.name,depth:1,expanded:!0,children:window2.panes.map((p)=>paneToNode(sessionName,window2.index,p,executorMap)),data:{active:window2.active,paneCount:window2.paneCount},activePanes,agentState:void 0}}function paneToNode(sessionName,windowIndex,pane,executorMap){let executor=executorMap.get(pane.paneId),isClaude=pane.command==="claude"||pane.title.includes("claude");return{id:`pane:${pane.paneId}`,type:"pane",label:derivePaneLabel(pane,executor,isClaude),depth:2,expanded:!1,children:[],data:{command:pane.command,isDead:pane.isDead,pid:pane.pid,size:pane.size,paneId:pane.paneId,sessionName,windowIndex},activePanes:0,agentState:derivePaneState(pane,executor)}}function derivePaneLabel(pane,executor,isClaude){if(executor?.agentName&&executor?.team)return`${executor.team}/${executor.agentName}`;if(executor?.agentName)return executor.agentName;if(isClaude)return"claude";return pane.command}function derivePaneState(pane,executor){if(pane.isDead)return"error";if(!executor)return;let s=executor.state;if(s==="working")return"working";if(s==="idle"||s==="spawning")return"idle";if(s==="permission")return"permission";if(s==="error"||s==="terminated")return"error";return}function getSessionTarget(node){if(node.type==="session")return{sessionName:node.label};if(node.type==="window"){let parts=node.id.split(":");return{sessionName:parts[1],windowIndex:Number(parts[2])}}if(node.type==="pane"){let data=node.data;return{sessionName:data.sessionName,windowIndex:data.windowIndex}}return null}function flattenTree(nodes){let result=[];function walk(node,depth){if(result.push({node,depth,visible:!0}),node.expanded)for(let child of node.children)walk(child,depth+1)}for(let node of nodes)walk(node,0);return result}function toggleNode(nodes,id){return nodes.map((node)=>{if(node.id===id)return{...node,expanded:!node.expanded};return{...node,children:toggleNode(node.children,id)}})}var import_jsx_dev_runtime2;var init_jsx_dev_runtime=__esm(()=>{import_jsx_dev_runtime2=__toESM(require_react_jsx_dev_runtime_development(),1)});function getNodeIcon(node){switch(node.type){case"session":return node.data.attached?"\u25B6":"\u25B8";case"window":return node.data.active?"\u25A0":"\u25A1";case"pane":return getPaneIcon(node);default:return" "}}function getPaneIcon(node){if(node.data.isDead)return"\u2718";if(node.agentState==="working")return"\u25CF";if(node.agentState==="idle")return"\u25CB";if(node.agentState==="permission")return"\u26A0";if(node.agentState==="error")return"\u2718";if(node.data.command==="claude")return"\u25C6";return"\u25CB"}function getNodeColor(node){switch(node.type){case"session":return node.data.attached?palette.emerald:palette.textDim;case"window":return node.data.active?palette.cyan:palette.text;case"pane":return getPaneColor(node);default:return palette.text}}function getPaneColor(node){if(node.data.isDead)return palette.error;if(node.agentState==="working")return palette.cyan;if(node.agentState==="permission")return palette.warning;if(node.agentState==="error")return palette.error;if(node.agentState==="idle")return palette.textDim;if(node.data.command==="claude")return palette.cyan;return palette.textDim}function getStateColor(state){switch(state){case"working":return palette.cyan;case"idle":return palette.textDim;case"permission":return palette.warning;case"error":return palette.error;default:return palette.textMuted}}var import_react13,TreeNodeRow;var init_TreeNode=__esm(()=>{init_theme2();init_jsx_dev_runtime();import_react13=__toESM(require_react_development(),1),TreeNodeRow=import_react13.memo(function({node,selected,onSelect,onToggle}){let indent=" ".repeat(node.depth),hasChildren=node.children.length>0,expandIcon=hasChildren?node.expanded?icons.expanded:icons.collapsed:" ",icon=getNodeIcon(node),color=getNodeColor(node),activeIndicator=node.activePanes>0?` ${icons.agent}${node.activePanes}`:"";return import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",backgroundColor:selected?palette.violet:void 0,onMouseDown:()=>{if(onSelect(node.id),hasChildren)onToggle(node.id)},children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:[indent,expandIcon," "]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:color,children:[icon," "]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:selected?"#ffffff":palette.text,children:node.label},void 0,!1,void 0,this),activeIndicator?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.cyan,children:activeIndicator},void 0,!1,void 0,this):null,node.agentState?import_jsx_dev_runtime2.jsxDEV("span",{fg:getStateColor(node.agentState),children:[" ",node.agentState]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)})});function Nav({onTmuxSessionSelect}){let[diagnostics,setDiagnostics]=import_react15.useState(null),[sessionTree,setSessionTree]=import_react15.useState([]),[selectedIndex,setSelectedIndex]=import_react15.useState(0),lastTarget=import_react15.useRef(null);import_react15.useEffect(()=>{let active=!0;async function refresh(){try{let snap=await collectDiagnostics();if(active)setDiagnostics(snap)}catch(err){console.error("TUI: diagnostics failed:",err)}}refresh();let timer2=setInterval(refresh,2000);return()=>{active=!1,clearInterval(timer2)}},[]),import_react15.useEffect(()=>{if(!diagnostics)return;let newTree=buildSessionTree(diagnostics);setSessionTree((prev)=>mergeExpandedState(prev,newTree))},[diagnostics]);let flatNodes=import_react15.useMemo(()=>flattenTree(sessionTree),[sessionTree]);import_react15.useEffect(()=>{if(flatNodes.length>0&&selectedIndex>=flatNodes.length)setSelectedIndex(flatNodes.length-1)},[flatNodes.length,selectedIndex]),import_react15.useEffect(()=>{let current=flatNodes[selectedIndex]?.node;if(!current)return;let target=getSessionTarget(current);if(!target)return;let key=`${target.sessionName}:${target.windowIndex??""}`;if(key===lastTarget.current)return;lastTarget.current=key,onTmuxSessionSelect(target.sessionName,target.windowIndex)},[selectedIndex,flatNodes,onTmuxSessionSelect]);let handleSelect=import_react15.useCallback((id)=>{let idx=flatNodes.findIndex((n)=>n.node.id===id);if(idx>=0)setSelectedIndex(idx)},[flatNodes]),handleToggle=import_react15.useCallback((id)=>{setSessionTree((prev)=>toggleNode(prev,id))},[]),handleVerticalNav=import_react15.useCallback((keyName2)=>{let rowCount=flatNodes.length;if(rowCount===0)return;if(keyName2==="up"||keyName2==="k")setSelectedIndex((prev)=>prev===0?rowCount-1:prev-1);else if(keyName2==="down"||keyName2==="j")setSelectedIndex((prev)=>prev>=rowCount-1?0:prev+1)},[flatNodes.length]),handleExpandCollapse=import_react15.useCallback((keyName2)=>{let node=flatNodes[selectedIndex]?.node;if(!node)return;if((keyName2==="right"||keyName2==="l")&&node.children.length>0&&!node.expanded)handleToggle(node.id);else if((keyName2==="left"||keyName2==="h")&&node.expanded)handleToggle(node.id)},[flatNodes,selectedIndex,handleToggle]),handleEnter=import_react15.useCallback(()=>{let node=flatNodes[selectedIndex]?.node;if(!node)return;if(node.children.length>0)handleToggle(node.id);let target=getSessionTarget(node);if(target)onTmuxSessionSelect(target.sessionName,target.windowIndex)},[flatNodes,selectedIndex,handleToggle,onTmuxSessionSelect]);useKeyboard((key)=>{if(key.name==="up"||key.name==="k"||key.name==="down"||key.name==="j")handleVerticalNav(key.name);else if(key.name==="right"||key.name==="l"||key.name==="left"||key.name==="h")handleExpandCollapse(key.name);else if(key.name==="enter"||key.name==="return")handleEnter()});let sessionCount=diagnostics?.sessions.length??0,totalPanes=diagnostics?.sessions.reduce((sum,s)=>sum+s.windows.reduce((ws,w2)=>ws+w2.panes.length,0),0)??0,deadPanes=diagnostics?.gaps.deadPaneCount??0;return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",width:"100%",height:"100%",backgroundColor:palette.bg,children:[import_jsx_dev_runtime2.jsxDEV("box",{height:1,paddingX:1,backgroundColor:palette.bgLight,children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.purple,children:"Sessions"},void 0,!1,void 0,this),diagnostics?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:[" ",sessionCount,"s ",totalPanes,"p"]},void 0,!0,void 0,this):null,deadPanes>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ",deadPanes,"\\u2620"]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this),diagnostics?import_jsx_dev_runtime2.jsxDEV("scrollbox",{focused:!0,height:"100%",style:{scrollbarOptions:{showArrows:!1,trackOptions:{foregroundColor:palette.scrollThumb,backgroundColor:palette.scrollTrack}}},children:flatNodes.map((flat,i2)=>import_jsx_dev_runtime2.jsxDEV(TreeNodeRow,{node:flat.node,selected:i2===selectedIndex,onSelect:handleSelect,onToggle:handleToggle},flat.node.id,!1,void 0,this))},void 0,!1,void 0,this):import_jsx_dev_runtime2.jsxDEV("box",{flexGrow:1,justifyContent:"center",alignItems:"center",children:import_jsx_dev_runtime2.jsxDEV("text",{fg:palette.textDim,children:"Collecting..."},void 0,!1,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("box",{height:1,paddingX:1,backgroundColor:palette.bgLight,children:import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:["\u2191\u2193",":nav ","\u2190\u2192",":expand Enter:attach"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function mergeExpandedState(oldTree,newTree){if(oldTree.length===0)return newTree;let oldState=new Map;function collect(nodes){for(let n of nodes)oldState.set(n.id,n.expanded),collect(n.children)}collect(oldTree);function apply(nodes){return nodes.map((n)=>({...n,expanded:oldState.has(n.id)?oldState.get(n.id):n.expanded,children:apply(n.children)}))}return apply(newTree)}var import_react15;var init_Nav=__esm(async()=>{init_diagnostics();init_theme2();init_TreeNode();init_jsx_dev_runtime();await init_react();import_react15=__toESM(require_react_development(),1)});function App({rightPane}){let renderer=useRenderer();useKeyboard((key)=>{if(key.name==="q"||key.ctrl&&key.name==="c")renderer.destroy(),cleanup()});let handleTmuxSessionSelect=import_react17.useCallback((sessionName,windowIndex)=>{if(!rightPane)return;attachProjectWindow(rightPane,sessionName,windowIndex)},[rightPane]);return import_jsx_dev_runtime2.jsxDEV(Nav,{onTmuxSessionSelect:handleTmuxSessionSelect},void 0,!1,void 0,this)}var import_react17;var init_app=__esm(async()=>{init_tmux2();init_jsx_dev_runtime();await __promiseAll([init_react(),init_Nav()]);import_react17=__toESM(require_react_development(),1)});var exports_render={};__export(exports_render,{renderNav:()=>renderNav});async function renderNav(){let rightPane=process.env.GENIE_TUI_RIGHT||void 0,renderer=await createCliRenderer({exitOnCtrlC:!1,useMouse:!0});createRoot(renderer).render(import_jsx_dev_runtime2.jsxDEV(App,{rightPane},void 0,!1,void 0,this))}var init_render=__esm(async()=>{init_jsx_dev_runtime();await __promiseAll([init_core(),init_react(),init_app()])});var exports_tui={};__export(exports_tui,{launchTui:()=>launchTui});async function launchTui(options={}){if(isInsideTuiSession()){let{renderNav:renderNav2}=await init_render().then(() => exports_render);await renderNav2();return}if(!hasTmux()){console.error("Error: tmux is required for genie tui");return}let{session,leftPane,rightPane}=createTuiSession(),bunPath=process.execPath||"bun",genieBin=process.argv[1]||"genie",{execSync:execSync15}=await import("child_process");if(options.dev)execSync15(`tmux send-keys -t '${leftPane}' "GENIE_TUI_PANE=left GENIE_TUI_RIGHT=${rightPane} bun --watch ${genieBin} tui" Enter`,{stdio:"ignore"});else execSync15(`tmux send-keys -t '${leftPane}' "GENIE_TUI_PANE=left GENIE_TUI_RIGHT=${rightPane} ${bunPath} ${genieBin} tui" Enter`,{stdio:"ignore"});attachTuiSession(),cleanup(session)}var init_tui=__esm(()=>{init_tmux2()});var import__=__toESM(require_commander(),1),{program,createCommand,createArgument,createOption,CommanderError,InvalidArgumentError,InvalidOptionArgumentError,Command,Argument,Option,Help}=import__.default;import{existsSync as existsSync3,unlinkSync as unlinkSync2}from"fs";import{homedir as homedir3}from"os";import{join as join3}from"path";var{$:$2}=globalThis.Bun;import{existsSync,unlinkSync}from"fs";import{homedir}from"os";import{join}from"path";var CLAUDE_DIR=join(homedir(),".claude"),CLAUDE_HOOKS_DIR=join(CLAUDE_DIR,"hooks"),CLAUDE_SETTINGS_FILE=join(CLAUDE_DIR,"settings.json"),GENIE_HOOK_SCRIPT_NAME="genie-bash-hook.sh";function getClaudeSettingsPath(){return CLAUDE_SETTINGS_FILE}function getGenieHookScriptPath(){return join(CLAUDE_HOOKS_DIR,GENIE_HOOK_SCRIPT_NAME)}function hookScriptExists(){return existsSync(getGenieHookScriptPath())}function removeHookScript(){let scriptPath=getGenieHookScriptPath();if(existsSync(scriptPath))unlinkSync(scriptPath)}function contractClaudePath(path){let home=homedir();if(path.startsWith(`${home}/`))return`~${path.slice(home.length)}`;if(path===home)return"~";return path}init_genie_config2();var{$}=globalThis.Bun;async function checkCommand(cmd){try{let cmdPath=(await $`which ${cmd}`.quiet().text()).trim();if(!cmdPath)return{exists:!1};let version;try{let firstLine=(await $`${cmd} --version`.quiet().text()).split(`
|
|
1905
1901
|
`)[0].trim(),versionMatch=firstLine.match(/(\d+\.[\d.]+[a-z0-9-]*)/i);version=versionMatch?versionMatch[1]:firstLine.slice(0,50)}catch{try{let firstLine=(await $`${cmd} -v`.quiet().text()).split(`
|
|
1906
1902
|
`)[0].trim(),versionMatch=firstLine.match(/(\d+\.[\d.]+[a-z0-9-]*)/i);version=versionMatch?versionMatch[1]:firstLine.slice(0,50)}catch{}}return{exists:!0,version,path:cmdPath}}catch{return{exists:!1}}}function printSectionHeader(title){console.log(),console.log(`\x1B[1m${title}:\x1B[0m`)}function printCheckResult(result){let icon={pass:"\x1B[32m\u2713\x1B[0m",fail:"\x1B[31m\u2717\x1B[0m",warn:"\x1B[33m!\x1B[0m"}[result.status],message=result.message?` ${result.message}`:"";if(console.log(` ${icon} ${result.name}${message}`),result.suggestion)console.log(` \x1B[2m${result.suggestion}\x1B[0m`)}async function checkPrerequisites(){let results=[],tmuxCheck=await checkCommand("tmux");if(tmuxCheck.exists)results.push({name:"tmux",status:"pass",message:tmuxCheck.version||""});else results.push({name:"tmux",status:"fail",suggestion:"Install with: brew install tmux (or apt install tmux)"});let jqCheck=await checkCommand("jq");if(jqCheck.exists)results.push({name:"jq",status:"pass",message:jqCheck.version||""});else results.push({name:"jq",status:"fail",suggestion:"Install with: brew install jq (or apt install jq)"});let bunCheck=await checkCommand("bun");if(bunCheck.exists)results.push({name:"bun",status:"pass",message:bunCheck.version||""});else results.push({name:"bun",status:"fail",suggestion:"Install with: curl -fsSL https://bun.sh/install | bash"});let claudeCheck=await checkCommand("claude");if(claudeCheck.exists)results.push({name:"Claude Code",status:"pass",message:claudeCheck.version||""});else results.push({name:"Claude Code",status:"warn",suggestion:"Install with: npm install -g @anthropic-ai/claude-code"});return results}async function checkConfiguration(){let results=[];if(genieConfigExists())results.push({name:"Genie config exists",status:"pass",message:contractClaudePath(getGenieConfigPath())});else results.push({name:"Genie config exists",status:"warn",message:"not found",suggestion:"Run: genie setup"});if(isSetupComplete())results.push({name:"Setup complete",status:"pass"});else results.push({name:"Setup complete",status:"warn",message:"not completed",suggestion:"Run: genie setup"});let claudeSettingsPath=getClaudeSettingsPath();if(existsSync3(claudeSettingsPath))results.push({name:"Claude settings exists",status:"pass",message:contractClaudePath(claudeSettingsPath)});else results.push({name:"Claude settings exists",status:"warn",message:"not found",suggestion:"Claude Code creates this on first run"});return results}async function checkTmux(){let results=[];try{if((await $2`tmux list-sessions 2>/dev/null`.quiet()).exitCode===0)results.push({name:"Server running",status:"pass"});else return results.push({name:"Server running",status:"warn",message:"no sessions",suggestion:"Start with: tmux new-session -d -s genie"}),results}catch{return results.push({name:"Server running",status:"warn",message:"could not check"}),results}let sessionName=(await loadGenieConfig()).session.name;try{if((await $2`tmux has-session -t ${sessionName} 2>/dev/null`.quiet()).exitCode===0)results.push({name:`Session '${sessionName}' exists`,status:"pass"});else results.push({name:`Session '${sessionName}' exists`,status:"warn",suggestion:`Start with: tmux new-session -d -s ${sessionName}`})}catch{results.push({name:`Session '${sessionName}' exists`,status:"warn",message:"could not check"})}return results}async function checkWorkerProfiles(){let results=[];if(!genieConfigExists())return results.push({name:"Worker profiles",status:"warn",message:"no genie config",suggestion:"Run: genie setup"}),results;let config=await loadGenieConfig(),profiles=config.workerProfiles;if(!profiles||Object.keys(profiles).length===0)return results.push({name:"Worker profiles",status:"pass",message:"none configured (using defaults)"}),results;let totalProfiles=Object.keys(profiles).length;results.push({name:"Profiles configured",status:"pass",message:`${totalProfiles} profile${totalProfiles===1?"":"s"}`});for(let name of Object.keys(profiles))results.push({name:`Profile '${name}'`,status:"pass",message:"claude (direct)"});if(config.defaultWorkerProfile)if(profiles[config.defaultWorkerProfile])results.push({name:"Default profile",status:"pass",message:config.defaultWorkerProfile});else results.push({name:"Default profile",status:"warn",message:`'${config.defaultWorkerProfile}' not found`,suggestion:"Run: genie profiles default <profile>"});return results}function runCheckSection(label,results,counts){printSectionHeader(label);for(let result of results){if(printCheckResult(result),result.status==="fail")counts.errors=!0;if(result.status==="warn")counts.warnings=!0}}async function doctorCommand(options){if(options?.fix){await doctorFix();return}console.log(),console.log("\x1B[1mGenie Doctor\x1B[0m"),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`);let counts={errors:!1,warnings:!1};if(runCheckSection("Prerequisites",await checkPrerequisites(),counts),runCheckSection("Configuration",await checkConfiguration(),counts),runCheckSection("Tmux",await checkTmux(),counts),runCheckSection("Worker Profiles",await checkWorkerProfiles(),counts),console.log(),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`),counts.errors)console.log("\x1B[31mSome checks failed.\x1B[0m Run \x1B[36mgenie setup\x1B[0m to fix.");else if(counts.warnings)console.log("\x1B[33mSome warnings detected.\x1B[0m Everything should still work.");else console.log("\x1B[32mAll checks passed!\x1B[0m");if(console.log(),counts.errors)process.exit(1)}async function doctorFix(){console.log(`
|
|
1907
1903
|
\x1B[1mGenie Doctor \u2014 Auto Fix\x1B[0m`),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m
|
|
@@ -1998,8 +1994,9 @@ Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.
|
|
|
1998
1994
|
`+` genie task status <slug> \u2014 check progress
|
|
1999
1995
|
`+" genie agent send --to <a> \u2014 communicate directly"},{test:/sleep\s+\d+\s*&&\s*.*(?:capture-pane|tmux\s+list)/,message:`Consider using genie primitives instead of terminal polling:
|
|
2000
1996
|
genie task status <slug>
|
|
2001
|
-
genie events list --since 5m`}];async function orchestrationGuard(payload){let command=payload.tool_input?.command;if(typeof command!=="string")return;for(let{test,message}of NUDGE_PATTERNS)if(test.test(command)){
|
|
2002
|
-
`)[0]}`;case"Grep":return`Grep "${input.pattern}" ${input.path??""}`;case"Glob":return`Glob ${input.pattern}`;case"Agent":return`Agent: ${input.description??""}`;case"SendMessage":return`SendMessage \u2192 ${input.to}: ${String(input.message??"").slice(0,80)}`;default:return name}}init_types3();var handlers=[{name:"branch-guard",event:"PreToolUse",matcher:/^Bash$/,priority:1,fn:branchGuard},{name:"orchestration-guard",event:"PreToolUse",matcher:/^Bash$/,priority:2,fn:orchestrationGuard},{name:"identity-inject",event:"PreToolUse",matcher:/^SendMessage$/,priority:10,fn:identityInject},{name:"auto-spawn",event:"PreToolUse",matcher:/^SendMessage$/,priority:20,fn:autoSpawn},{name:"runtime-emit-tool",event:"PreToolUse",matcher:/.*/,priority:30,fn:emitToolCallEvent},{name:"runtime-emit-msg",event:"PostToolUse",matcher:/^SendMessage$/,priority:30,fn:emitMessageEvent},{name:"runtime-emit-user-prompt",event:"UserPromptSubmit",priority:30,fn:emitUserPromptEvent},{name:"runtime-emit-assistant-response",event:"Stop",priority:30,fn:emitAssistantResponseEvent}];function resolveHandlers(event,toolName){return handlers.filter((h)=>{if(h.event!==event)return!1;if(h.matcher&&toolName&&!h.matcher.test(toolName))return!1;if(h.matcher&&!toolName)return!1;return!0}).sort((a,b2)=>a.priority-b2.priority)}async function runHandler(handler,payload,currentInput){let handlerPayload={...payload};if(currentInput)handlerPayload.tool_input=currentInput;try{return await handler.fn(handlerPayload)}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`[genie-hook] Handler "${handler.name}" threw: ${msg}`);return}}async function executeBlockingChain(matched,payload){let currentInput=payload.tool_input?{...payload.tool_input}:void 0;for(let handler of matched){let result=await runHandler(handler,payload,currentInput);if(!result)continue;if(result.decision==="deny")return{decision:"deny",reason:result.reason??`Denied by handler: ${handler.name}`};if(result.updatedInput)currentInput={...currentInput,...result.updatedInput}}if(currentInput&&payload.tool_input&&JSON.stringify(currentInput)!==JSON.stringify(payload.tool_input))
|
|
1997
|
+
genie events list --since 5m`}];async function orchestrationGuard(payload){let command=payload.tool_input?.command;if(typeof command!=="string")return;for(let{test,message}of NUDGE_PATTERNS)if(test.test(command))return{systemMessage:`[orchestration-guard] ${message}`};return}var getAgent2=()=>process.env.GENIE_AGENT_NAME??"unknown",getTeam=()=>process.env.GENIE_TEAM;async function emit(subject,event){try{let{publishSubjectEvent:publishSubjectEvent2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events));await publishSubjectEvent2(process.cwd(),subject,event)}catch{}}async function emitToolCallEvent(payload){let{tool_name:toolName,tool_input:input}=payload;if(!toolName||!input)return;await emit(`genie.tool.${getAgent2()}.call`,{timestamp:new Date().toISOString(),kind:"tool_call",agent:getAgent2(),team:getTeam(),text:summarizeToolCall(toolName,input),data:{toolCall:{name:toolName,input}},source:"hook"});return}async function emitMessageEvent(payload){let input=payload.tool_input;if(!input)return;let msgType=input.type;if(msgType&&msgType!=="message"&&msgType!=="broadcast")return;let to=input.to,content=input.content??input.message;if(!to||!content)return;let subject=msgType==="broadcast"?"genie.msg.broadcast":`genie.msg.${to}`;await emit(subject,{timestamp:new Date().toISOString(),kind:"message",agent:getAgent2(),team:getTeam(),peer:to,direction:"out",text:content,source:"hook"});return}async function emitUserPromptEvent(payload){let prompt2=payload.prompt;if(!prompt2)return;await emit(`genie.user.${getAgent2()}.prompt`,{timestamp:new Date().toISOString(),kind:"user",agent:getAgent2(),team:getTeam(),text:prompt2,source:"hook"});return}async function emitAssistantResponseEvent(payload){let lastMessage=payload.last_assistant_message;if(!lastMessage)return;await emit(`genie.agent.${getAgent2()}.response`,{timestamp:new Date().toISOString(),kind:"assistant",agent:getAgent2(),team:getTeam(),text:lastMessage,source:"hook"});return}function summarizeToolCall(name,input){switch(name){case"Read":case"Edit":case"Write":return`${name} ${input.file_path??""}`;case"Bash":return`$ ${String(input.command??"").split(`
|
|
1998
|
+
`)[0]}`;case"Grep":return`Grep "${input.pattern}" ${input.path??""}`;case"Glob":return`Glob ${input.pattern}`;case"Agent":return`Agent: ${input.description??""}`;case"SendMessage":return`SendMessage \u2192 ${input.to}: ${String(input.message??"").slice(0,80)}`;default:return name}}init_types3();var handlers=[{name:"branch-guard",event:"PreToolUse",matcher:/^Bash$/,priority:1,fn:branchGuard},{name:"orchestration-guard",event:"PreToolUse",matcher:/^Bash$/,priority:2,fn:orchestrationGuard},{name:"identity-inject",event:"PreToolUse",matcher:/^SendMessage$/,priority:10,fn:identityInject},{name:"auto-spawn",event:"PreToolUse",matcher:/^SendMessage$/,priority:20,fn:autoSpawn},{name:"runtime-emit-tool",event:"PreToolUse",matcher:/.*/,priority:30,fn:emitToolCallEvent},{name:"runtime-emit-msg",event:"PostToolUse",matcher:/^SendMessage$/,priority:30,fn:emitMessageEvent},{name:"runtime-emit-user-prompt",event:"UserPromptSubmit",priority:30,fn:emitUserPromptEvent},{name:"runtime-emit-assistant-response",event:"Stop",priority:30,fn:emitAssistantResponseEvent}];function resolveHandlers(event,toolName){return handlers.filter((h)=>{if(h.event!==event)return!1;if(h.matcher&&toolName&&!h.matcher.test(toolName))return!1;if(h.matcher&&!toolName)return!1;return!0}).sort((a,b2)=>a.priority-b2.priority)}async function runHandler(handler,payload,currentInput){let handlerPayload={...payload};if(currentInput)handlerPayload.tool_input=currentInput;try{return await handler.fn(handlerPayload)}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`[genie-hook] Handler "${handler.name}" threw: ${msg}`);return}}async function executeBlockingChain(matched,payload){let currentInput=payload.tool_input?{...payload.tool_input}:void 0,messages2=[];for(let handler of matched){let result=await runHandler(handler,payload,currentInput);if(!result)continue;if(result.decision==="deny")return{decision:"deny",reason:result.reason??`Denied by handler: ${handler.name}`};if(result.systemMessage)messages2.push(result.systemMessage);if(result.updatedInput)currentInput={...currentInput,...result.updatedInput}}let response={};if(currentInput&&payload.tool_input&&JSON.stringify(currentInput)!==JSON.stringify(payload.tool_input))response.updatedInput=currentInput;if(messages2.length>0)response.systemMessage=messages2.join(`
|
|
1999
|
+
`);return response}async function executeNonBlockingHandlers(matched,payload){await Promise.allSettled(matched.map((h)=>h.fn(payload).catch((err)=>{let msg=err instanceof Error?err.message:String(err);console.error(`[genie-hook] Handler "${h.name}" threw: ${msg}`)})))}async function dispatch(stdin){let payload;try{payload=JSON.parse(stdin)}catch{return console.error("[genie-hook] Invalid JSON on stdin"),""}let event=payload.hook_event_name;if(!event)return console.error("[genie-hook] Missing hook_event_name in payload"),"";let toolName=payload.tool_name,matched=resolveHandlers(event,toolName);if(matched.length===0)return"";if(isBlockingEvent(event)){let result=await executeBlockingChain(matched,payload);if(result.decision||result.updatedInput||result.systemMessage)return JSON.stringify(result);return""}return await executeNonBlockingHandlers(matched,payload),""}async function readStdin(){let chunks=[];for await(let chunk of Bun.stdin.stream())chunks.push(Buffer.from(chunk));return Buffer.concat(chunks).toString("utf-8")}async function dispatchAction(){let stdin=await readStdin();if(!stdin.trim())process.exit(0);let result=await dispatch(stdin);if(result)process.stdout.write(result)}function registerHookNamespace(program2){program2.command("hook").description("Hook middleware for Claude Code integration").command("dispatch").description("Dispatch a CC hook event (reads JSON from stdin, writes decision to stdout)").action(dispatchAction)}init_audit();init_db();init_otel_receiver();init_target_resolver();init_tmux();init_orchestrator();async function resolveOrcTarget(target){let resolved=await resolveTarget(target);return{paneId:resolved.paneId,session:resolved.session||target,label:formatResolvedLabel(resolved,target)}}async function sendTextChoice(paneId,text){await executeTmux2(`send-keys -t '${paneId}' End`),await sleep(100),await executeTmux2(`send-keys -t '${paneId}' Enter`),await sleep(100),await executeTmux2(`send-keys -t '${paneId}' ${shellEscape(text)}`),await sleep(100),await executeTmux2(`send-keys -t '${paneId}' Enter`)}function findCurrentOption(output){let lines=stripAnsi(output).split(`
|
|
2003
2000
|
`);for(let line of lines){let match=line.match(/^\s*\u276F\s*(\d+)\./);if(match)return Number.parseInt(match[1],10)}return 1}async function navigateToOption(paneId,targetOption,currentOption){let diff=targetOption-currentOption,key=diff>0?"Down":"Up";for(let i2=0;i2<Math.abs(diff);i2++)await executeTmux2(`send-keys -t '${paneId}' ${key}`),await sleep(50);await sleep(100),await executeTmux2(`send-keys -t '${paneId}' Enter`)}async function answerQuestion(target,choice){try{let{paneId,label}=await resolveOrcTarget(target),output=await capturePaneContent(paneId,50),state=detectState(output);if(state.type!=="question"){console.log(`No question pending (state: ${state.type})`);return}if(choice.startsWith("text:")){let text=choice.slice(5);await sendTextChoice(paneId,text),console.log(`Sent feedback: "${text.substring(0,50)}${text.length>50?"...":""}"`)}else if(/^\d+$/.test(choice)){let targetOption=Number.parseInt(choice,10);await navigateToOption(paneId,targetOption,findCurrentOption(output)),console.log(`Selected option ${targetOption} for ${label}`)}else await executeTmux2(`send-keys -t '${paneId}' '${choice}'`),console.log(`Sent '${choice}' to ${label}`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function shellEscape(str2){return`"${str2.replace(/"/g,"\\\"").replace(/\$/g,"\\$")}"`}function sleep(ms){return new Promise((resolve4)=>setTimeout(resolve4,ms))}function registerAgentAnswer(parent){parent.command("answer <name> <choice>").description('Answer a question for an agent (use "text:..." for text input)').action(async(name,choice)=>{try{await answerQuestion(name,choice)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}var _brief;async function getBrief(){if(!_brief)_brief=await Promise.resolve().then(() => (init_brief(),exports_brief));return _brief}async function handleBrief(options){let team=options.team??process.env.GENIE_TEAM;if(!team)console.error("Error: --team is required (or set GENIE_TEAM)"),process.exit(1);let agent=options.agent??process.env.GENIE_AGENT_NAME,briefService=await getBrief(),brief=await briefService.generateBrief({team,agent,since:options.since,repoPath:process.cwd()});console.log(briefService.formatBrief(brief))}function registerAgentBrief(parent){parent.command("brief").description("Show startup brief \u2014 aggregated context since last session").option("--team <name>","Team name (default: GENIE_TEAM)").option("--agent <name>","Agent name (default: GENIE_AGENT_NAME)").option("--since <iso>","Start timestamp (default: last executor end)").action(async(options)=>{try{await handleBrief(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_audit();init_db();import{existsSync as existsSync18,readFileSync as readFileSync9,renameSync as renameSync2,writeFileSync as writeFileSync6}from"fs";import{homedir as homedir15}from"os";import{join as join19}from"path";var GENIE_HOME3=process.env.GENIE_HOME??join19(homedir15(),".genie"),CACHE_FILE="agent-directory.json",CACHE_BACKUP="agent-directory.json.bak";async function regenerateAgentCache(){try{if(!await isAvailable())return;let entries=(await(await getConnection())`
|
|
2004
2001
|
SELECT name, install_path, manifest, installed_at
|
|
2005
2002
|
FROM app_store
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genie",
|
|
3
|
-
"version": "4.260329.
|
|
3
|
+
"version": "4.260329.22",
|
|
4
4
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, turn them into wishes, execute with /work, validate with /review, and ship as one team.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Namastex Labs"
|
|
@@ -47,10 +47,9 @@ export async function orchestrationGuard(payload: HookPayload): Promise<HandlerR
|
|
|
47
47
|
|
|
48
48
|
for (const { test, message } of NUDGE_PATTERNS) {
|
|
49
49
|
if (test.test(command)) {
|
|
50
|
-
// Informational
|
|
51
|
-
// but
|
|
52
|
-
|
|
53
|
-
return undefined;
|
|
50
|
+
// Informational nudge — systemMessage is shown to the agent
|
|
51
|
+
// but does not block the command from executing.
|
|
52
|
+
return { systemMessage: `[orchestration-guard] ${message}` };
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
|
package/src/hooks/index.ts
CHANGED
|
@@ -123,6 +123,7 @@ async function runHandler(
|
|
|
123
123
|
|
|
124
124
|
async function executeBlockingChain(matched: Handler[], payload: HookPayload): Promise<HookDecision> {
|
|
125
125
|
let currentInput = payload.tool_input ? { ...payload.tool_input } : undefined;
|
|
126
|
+
const messages: string[] = [];
|
|
126
127
|
|
|
127
128
|
for (const handler of matched) {
|
|
128
129
|
const result = await runHandler(handler, payload, currentInput);
|
|
@@ -131,16 +132,23 @@ async function executeBlockingChain(matched: Handler[], payload: HookPayload): P
|
|
|
131
132
|
if (result.decision === 'deny') {
|
|
132
133
|
return { decision: 'deny', reason: result.reason ?? `Denied by handler: ${handler.name}` };
|
|
133
134
|
}
|
|
135
|
+
if (result.systemMessage) {
|
|
136
|
+
messages.push(result.systemMessage);
|
|
137
|
+
}
|
|
134
138
|
if (result.updatedInput) {
|
|
135
139
|
currentInput = { ...currentInput, ...result.updatedInput };
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
const response: HookDecision = {};
|
|
139
144
|
if (currentInput && payload.tool_input && JSON.stringify(currentInput) !== JSON.stringify(payload.tool_input)) {
|
|
140
|
-
|
|
145
|
+
response.updatedInput = currentInput;
|
|
146
|
+
}
|
|
147
|
+
if (messages.length > 0) {
|
|
148
|
+
response.systemMessage = messages.join('\n');
|
|
141
149
|
}
|
|
142
150
|
|
|
143
|
-
return
|
|
151
|
+
return response;
|
|
144
152
|
}
|
|
145
153
|
|
|
146
154
|
async function executeNonBlockingHandlers(matched: Handler[], payload: HookPayload): Promise<void> {
|
|
@@ -184,8 +192,8 @@ export async function dispatch(stdin: string): Promise<string> {
|
|
|
184
192
|
|
|
185
193
|
if (isBlockingEvent(event)) {
|
|
186
194
|
const result = await executeBlockingChain(matched, payload);
|
|
187
|
-
//
|
|
188
|
-
if (result.decision || result.updatedInput) {
|
|
195
|
+
// Output JSON if there's a decision, update, or informational message
|
|
196
|
+
if (result.decision || result.updatedInput || result.systemMessage) {
|
|
189
197
|
return JSON.stringify(result);
|
|
190
198
|
}
|
|
191
199
|
return '';
|
package/src/hooks/types.ts
CHANGED
|
@@ -46,6 +46,8 @@ export interface HookDecision {
|
|
|
46
46
|
decision?: 'allow' | 'deny' | 'ask';
|
|
47
47
|
reason?: string;
|
|
48
48
|
updatedInput?: Record<string, unknown>;
|
|
49
|
+
/** Informational message shown to the agent without blocking. */
|
|
50
|
+
systemMessage?: string;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/** Result from a handler — either a decision or void (implicit allow). */
|