@automagik/genie 4.260329.7 → 4.260329.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "genie",
|
|
13
|
-
"version": "4.260329.
|
|
13
|
+
"version": "4.260329.8",
|
|
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
|
@@ -1808,7 +1808,7 @@ $ bun add react-devtools-core@7 -d
|
|
|
1808
1808
|
AND a.ended_at IS NULL
|
|
1809
1809
|
ORDER BY a.started_at DESC
|
|
1810
1810
|
`).map(mapAssignment)}function mapOrg(row){return{id:String(row.id),name:String(row.name),slug:String(row.slug),description:row.description?String(row.description):null,leaderAgent:row.leader_agent?String(row.leader_agent):null}}function mapProject2(row){return{id:String(row.id),name:String(row.name),description:row.description?String(row.description):null,orgId:row.org_id?String(row.org_id):null,leaderAgent:row.leader_agent?String(row.leader_agent):null,tmuxSession:row.tmux_session?String(row.tmux_session):null,repoPath:row.repo_path?String(row.repo_path):null}}function mapBoard2(row){let rawCols=row.columns,columns=Array.isArray(rawCols)?rawCols.map((c,i2)=>({id:String(c.id??`col-${i2}`),name:String(c.name??""),label:String(c.label??c.name??""),color:String(c.color??"#94a3b8"),position:typeof c.position==="number"?c.position:i2})):[];return{id:String(row.id),name:String(row.name),projectId:row.project_id?String(row.project_id):null,description:row.description?String(row.description):null,columns}}function mapTask2(row){return{id:String(row.id),seq:Number(row.seq),title:String(row.title),status:String(row.status),stage:String(row.stage),priority:String(row.priority),projectId:row.project_id?String(row.project_id):null,boardId:row.board_id?String(row.board_id):null,columnId:row.column_id?String(row.column_id):null,description:row.description?String(row.description):null}}function mapAgentProject(row){return{agentName:String(row.agent_name),projectId:String(row.project_id),role:String(row.role)}}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]=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}}}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}'");if(!paneOutput)return[];let sessionMap=new Map,windowMap=new Map;for(let line of paneOutput.split(`
|
|
1811
|
-
`)){if(!line)continue;let parts=line.split("|");if(parts.length<14)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;return{deadPidExecutors,orphanPanes,linkedCount,totalExecutors:executors.length,totalClaudePanes:claudePanes.length}}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 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)),rows=executors.flatMap((exec3)=>executorToRows(exec3,assignments,deadIds.has(exec3.id)));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=0;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 TabBar({activeTab,focused,gaps}){let totalGaps=(gaps?.orphanProcesses??0)+(gaps?.orphanPanes??0);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,badge=tab==="claude"&&totalGaps>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ",totalGaps]},void 0,!0,void 0,this):null;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),badge]},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=["projects","tmux","claude"],TAB_LABELS={projects:"Projects",tmux:"tmux",claude:"Claude"}});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},windowRows=session.windows.flatMap((window2)=>{let 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${window2.active?" *":""}`,detailColor:window2.active?palette.cyan:palette.textMuted,type:"window",sessionName:session.name,isClaude:!1},paneRows=window2.panes.map((pane)=>{let isClaude=pane.command==="claude"||pane.title.includes("claude");return{id:`p:${pane.paneId}`,depth:2,label:`${pane.paneId} [${pane.command}]`,color:isClaude?palette.cyan:palette.textDim,detail:`pid:${pane.pid} ${pane.size}`,detailColor:palette.textMuted,type:"pane",sessionName:session.name,isClaude}});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);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)},void 0,!1,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":"\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}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}){let[activeTab,setActiveTab]=import_react17.useState("projects"),[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")return;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)},[activeTab,flatNodes,projectIndex,onProjectSelect,handleToggle]),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}: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]);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},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_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",devFlag=options.dev?" --dev":"",{execSync:execSync15}=await import("child_process");execSync15(`tmux send-keys -t '${leftPane}' "GENIE_TUI_PANE=left GENIE_TUI_RIGHT=${rightPane} ${bunPath} ${genieBin} tui${devFlag}" 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(`
|
|
1811
|
+
`)){if(!line)continue;let parts=line.split("|");if(parts.length<14)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;return{deadPidExecutors,orphanPanes,linkedCount,totalExecutors:executors.length,totalClaudePanes:claudePanes.length}}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 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)),rows=executors.flatMap((exec3)=>executorToRows(exec3,assignments,deadIds.has(exec3.id)));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=0;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 TabBar({activeTab,focused,gaps}){let totalGaps=(gaps?.orphanProcesses??0)+(gaps?.orphanPanes??0);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,badge=tab==="claude"&&totalGaps>0?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ",totalGaps]},void 0,!0,void 0,this):null;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),badge]},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=["projects","tmux","claude"],TAB_LABELS={projects:"Projects",tmux:"tmux",claude:"Claude"}});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},windowRows=session.windows.flatMap((window2)=>{let 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${window2.active?" *":""}`,detailColor:window2.active?palette.cyan:palette.textMuted,type:"window",sessionName:session.name,isClaude:!1},paneRows=window2.panes.map((pane)=>{let isClaude=pane.command==="claude"||pane.title.includes("claude");return{id:`p:${pane.paneId}`,depth:2,label:`${pane.paneId} [${pane.command}]`,color:isClaude?palette.cyan:palette.textDim,detail:`pid:${pane.pid} ${pane.size}`,detailColor:palette.textMuted,type:"pane",sessionName:session.name,isClaude}});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);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)},void 0,!1,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":"\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}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}){let[activeTab,setActiveTab]=import_react17.useState("projects"),[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")return;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)},[activeTab,flatNodes,projectIndex,onProjectSelect,handleToggle]),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}: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]);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},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_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: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(`
|
|
1812
1812
|
`)[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(`
|
|
1813
1813
|
`)[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(`
|
|
1814
1814
|
\x1B[1mGenie Doctor \u2014 Auto Fix\x1B[0m`),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m
|
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.8",
|
|
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"
|
package/src/tui/index.ts
CHANGED
|
@@ -27,14 +27,21 @@ export async function launchTui(options: { dev?: boolean } = {}): Promise<void>
|
|
|
27
27
|
// Send the nav command to the left pane
|
|
28
28
|
const bunPath = process.execPath || 'bun';
|
|
29
29
|
const genieBin = process.argv[1] || 'genie';
|
|
30
|
-
const devFlag = options.dev ? ' --dev' : '';
|
|
31
30
|
|
|
32
31
|
// Run the TUI nav renderer in the left pane
|
|
32
|
+
// Dev mode: bun --watch auto-restarts on source file changes
|
|
33
33
|
const { execSync } = await import('node:child_process');
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
if (options.dev) {
|
|
35
|
+
execSync(
|
|
36
|
+
`tmux send-keys -t '${leftPane}' "GENIE_TUI_PANE=left GENIE_TUI_RIGHT=${rightPane} bun --watch ${genieBin} tui" Enter`,
|
|
37
|
+
{ stdio: 'ignore' },
|
|
38
|
+
);
|
|
39
|
+
} else {
|
|
40
|
+
execSync(
|
|
41
|
+
`tmux send-keys -t '${leftPane}' "GENIE_TUI_PANE=left GENIE_TUI_RIGHT=${rightPane} ${bunPath} ${genieBin} tui" Enter`,
|
|
42
|
+
{ stdio: 'ignore' },
|
|
43
|
+
);
|
|
44
|
+
}
|
|
38
45
|
|
|
39
46
|
// Attach (blocking)
|
|
40
47
|
attachTuiSession();
|