@automagik/genie 4.260329.2 → 4.260329.4
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 +3 -2
- 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/tui/components/Nav.tsx +11 -0
- package/src/tui/tmux.ts +43 -9
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "genie",
|
|
13
|
-
"version": "4.260329.
|
|
13
|
+
"version": "4.260329.4",
|
|
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
|
@@ -1330,7 +1330,8 @@ ${answer}
|
|
|
1330
1330
|
`).map((r)=>r.table_name)}async function filterAvailableTables(sql,requested){let existing=new Set(await getAvailableTables(sql)),available=[],skipped=[];for(let table of requested)if(existing.has(table))available.push(table);else skipped.push(table);return{available,skipped}}var exports_codex_logs={};__export(exports_codex_logs,{parseCodexLine:()=>parseCodexLine,extractCodexContent:()=>extractCodexContent,codexTranscriptProvider:()=>codexTranscriptProvider});import{access as access2,readFile as readFile8,readdir as readdir5}from"fs/promises";import{homedir as homedir22}from"os";import{join as join34}from"path";function getCodexDir(){return join34(homedir22(),".codex")}function getSessionsDir(){return join34(getCodexDir(),"sessions")}function getStateDbPath(){return join34(getCodexDir(),"state_5.sqlite")}async function discoverLogPath(worker){let cwd=worker.worktree||worker.repoPath,sqlitePath=await discoverViaSqlite(cwd);if(sqlitePath)try{return await access2(sqlitePath),sqlitePath}catch{}return discoverViaScan(cwd)}async function discoverViaSqlite(cwd){try{let{Database}=await import("bun:sqlite"),dbPath=getStateDbPath(),db=new Database(dbPath,{readonly:!0});try{return db.query("SELECT rollout_path FROM threads WHERE cwd = ? ORDER BY updated_at DESC LIMIT 1").get(cwd)?.rollout_path??null}finally{db.close()}}catch{return null}}async function listDirsDesc(parent,pattern){return(await readdir5(parent)).filter((d)=>pattern.test(d)).sort().reverse()}async function discoverViaScan(cwd){let sessionsDir=getSessionsDir();try{let years=await listDirsDesc(sessionsDir,/^\d{4}$/);for(let year of years.slice(0,2)){let result=await scanYear(join34(sessionsDir,year),cwd);if(result)return result}}catch{}return null}async function scanYear(yearDir,cwd){let months=await listDirsDesc(yearDir,/^\d{2}$/);for(let month of months.slice(0,2)){let result=await scanMonth(join34(yearDir,month),cwd);if(result)return result}return null}async function scanMonth(monthDir,cwd){let days=await listDirsDesc(monthDir,/^\d{2}$/);for(let day of days.slice(0,3)){let result=await scanDay(join34(monthDir,day),cwd);if(result)return result}return null}async function scanDay(dayDir,cwd){let files=(await readdir5(dayDir)).filter((f)=>f.endsWith(".jsonl")).sort().reverse();for(let file of files.slice(0,5)){let filePath=join34(dayDir,file);if((await readSessionMeta(filePath))?.cwd===cwd)return filePath}return null}async function readSessionMeta(filePath){try{let content=await readFile8(filePath,"utf-8"),nlIdx=content.indexOf(`
|
|
1331
1331
|
`),firstLine=nlIdx===-1?content:content.slice(0,nlIdx),entry=JSON.parse(firstLine);if(entry.type==="session_meta"&&entry.payload?.cwd)return{cwd:entry.payload.cwd}}catch{}return null}function parseEventMsg(payload,ts3,base){if(payload.type==="user_message"){let text=String(payload.message??"");return text?[{...base,role:"user",timestamp:ts3,text}]:[]}if(payload.type==="agent_message"){let text=String(payload.message??"");return text?[{...base,role:"assistant",timestamp:ts3,text}]:[]}return[]}function parseResponseMessage(payload,ts3,base){let role=payload.role,text=extractCodexContent(payload.content);if(!text)return[];if(role==="user")return[{...base,role:"user",timestamp:ts3,text}];if(role==="developer")return[{...base,role:"system",timestamp:ts3,text}];if(role==="assistant")return[{...base,role:"assistant",timestamp:ts3,text}];return[]}function parseFunctionCall(payload,ts3,base){let name=String(payload.name??payload.type),callId=String(payload.call_id??""),input={};try{input=typeof payload.arguments==="string"?JSON.parse(payload.arguments):{}}catch{input={raw:payload.arguments}}let cmdText=input.command?String(Array.isArray(input.command)?input.command.join(" "):input.command):name;return[{...base,role:"tool_call",timestamp:ts3,text:`${name}: ${cmdText.slice(0,200)}`,toolCall:{id:callId,name,input}}]}function parseWebSearch(payload,ts3,base){let action=payload.action,query=String(action?.query??"web search");return[{...base,role:"tool_call",timestamp:ts3,text:`web_search: ${query.slice(0,200)}`,toolCall:{id:"",name:"web_search",input:{query}}}]}function parseResponseItem(payload,ts3,base){if(payload.type==="message")return parseResponseMessage(payload,ts3,base);if(payload.type==="function_call"||payload.type==="shell")return parseFunctionCall(payload,ts3,base);if(payload.type==="function_call_output"){let output=String(payload.output??"").slice(0,500);return[{...base,role:"tool_result",timestamp:ts3,text:output}]}if(payload.type==="web_search_call")return parseWebSearch(payload,ts3,base);return[]}function parseCodexLine(line){if(!line.trim())return[];let raw;try{raw=JSON.parse(line)}catch{return[]}if(!raw.type||!raw.timestamp)return[];let base={provider:"codex",raw};if(!raw.payload||typeof raw.payload!=="object")return[];if(raw.type==="event_msg")return parseEventMsg(raw.payload,raw.timestamp,base);if(raw.type==="response_item")return parseResponseItem(raw.payload,raw.timestamp,base);return[]}function extractCodexContent(content){if(typeof content==="string")return content;if(!Array.isArray(content))return"";let parts=[];for(let item of content)if(typeof item==="string")parts.push(item);else if(item&&typeof item==="object"){if("text"in item)parts.push(String(item.text));else if("input_text"in item)parts.push(String(item.input_text))}return parts.join(" ")}async function readEntries(logPath){let content;try{content=await readFile8(logPath,"utf-8")}catch{return[]}return content.split(`
|
|
1332
1332
|
`).flatMap(parseCodexLine)}var codexTranscriptProvider;var init_codex_logs=__esm(()=>{codexTranscriptProvider={discoverLogPath,readEntries}});var exports_transcript={};__export(exports_transcript,{readTranscript:()=>readTranscript,getProvider:()=>getProvider2,applyFilter:()=>applyFilter});function applyFilter(entries,filter){if(!filter)return entries;let result=entries;if(filter.since){let sinceMs=new Date(filter.since).getTime();result=result.filter((e)=>new Date(e.timestamp).getTime()>=sinceMs)}if(filter.roles&&filter.roles.length>0){let roles=new Set(filter.roles);result=result.filter((e)=>roles.has(e.role))}if(filter.last&&filter.last>0)result=result.slice(-filter.last);return result}async function getClaudeProvider(){if(!_claudeProvider)_claudeProvider=(await Promise.resolve().then(() => (init_claude_logs(),exports_claude_logs))).claudeTranscriptProvider;return _claudeProvider}async function getCodexProvider(){if(!_codexProvider)_codexProvider=(await Promise.resolve().then(() => (init_codex_logs(),exports_codex_logs))).codexTranscriptProvider;return _codexProvider}async function getProvider2(worker){if((worker.provider??"claude")==="codex")return getCodexProvider();return getClaudeProvider()}async function readTranscript(worker,filter){let provider=await getProvider2(worker),logPath=await provider.discoverLogPath(worker);if(!logPath)return[];let entries=await provider.readEntries(logPath);return applyFilter(entries,filter)}var _claudeProvider,_codexProvider;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 execSync12,spawnSync as spawnSync2}from"child_process";function hasTmux(){try{return execSync12("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{execSync12(`tmux kill-session -t ${SESSION_NAME} 2>/dev/null`,{stdio:"ignore"})}catch{}execSync12(`tmux new-session -d -s ${SESSION_NAME} -x ${cols} -y ${rows} -e GENIE_TUI_PANE=left`,{stdio:"ignore"}),execSync12(`tmux split-window -h -t ${SESSION_NAME}:0 -l ${cols-NAV_WIDTH-1}`,{stdio:"ignore"});let panes=execSync12(`tmux list-panes -t ${SESSION_NAME}:0 -F '#{pane_id}'`,{encoding:"utf-8"}).trim().split(`
|
|
1333
|
-
`),leftPane=panes[0],rightPane=panes[1]||panes[0];return applyTmuxStyle(SESSION_NAME),setupKeybindings(SESSION_NAME),{session:SESSION_NAME,leftPane,rightPane}}function
|
|
1333
|
+
`),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 execSync12(`tmux display-message -t ${rightPane} -p ''`,{stdio:"ignore"}),rightPane}catch{try{let panes=execSync12(`tmux list-panes -t ${SESSION_NAME}:0 -F '#{pane_id}'`,{encoding:"utf-8"}).trim().split(`
|
|
1334
|
+
`);return panes[1]||panes[0]}catch{return rightPane}}}function ensureSession3(sessionName){try{execSync12(`tmux has-session -t '${sessionName}' 2>/dev/null`,{stdio:"ignore"})}catch{try{execSync12(`tmux new-session -d -s '${sessionName}'`,{stdio:"ignore"})}catch{}}}function attachProject(rightPane,targetSession){let pane=resolveRightPane(rightPane);ensureSession3(targetSession);try{execSync12(`tmux respawn-pane -k -t ${pane} "TMUX='' tmux attach-session -t '${targetSession}'"`,{stdio:"ignore"})}catch{}}function switchRightPane(rightPane,targetSession){attachProject(rightPane,targetSession)}function setupKeybindings(session){try{execSync12(`tmux bind-key -T ${KEY_TABLE} Tab select-pane -t ${session}:0.+ \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync12(`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"}),execSync12(`tmux bind-key -T ${KEY_TABLE} C-t send-keys -t ${session}:0.1 C-b c \\; switch-client -T ${KEY_TABLE}`,{stdio:"ignore"}),execSync12(`tmux bind-key -T ${KEY_TABLE} 'C-\\' run-shell "tmux kill-session -t ${session}"`,{stdio:"ignore"}),execSync12(`tmux set-hook -t ${session} client-session-changed "switch-client -T ${KEY_TABLE}"`,{stdio:"ignore"}),execSync12(`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)execSync12(`tmux ${cmd}`,{stdio:"ignore"})}catch{}}function cleanup(session=SESSION_NAME){try{execSync12(`tmux unbind-key -T ${KEY_TABLE} Tab 2>/dev/null`,{stdio:"ignore"}),execSync12(`tmux unbind-key -T ${KEY_TABLE} C-b 2>/dev/null`,{stdio:"ignore"}),execSync12(`tmux unbind-key -T ${KEY_TABLE} C-t 2>/dev/null`,{stdio:"ignore"}),execSync12(`tmux unbind-key -T ${KEY_TABLE} 'C-\\' 2>/dev/null`,{stdio:"ignore"}),execSync12(`tmux set-hook -u -t ${session} client-session-changed 2>/dev/null`,{stdio:"ignore"}),execSync12(`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=execSync12(`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(`
|
|
1334
1335
|
`).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:
|
|
1335
1336
|
`+treeLines.join(`
|
|
1336
1337
|
`))}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(`
|
|
@@ -1798,7 +1799,7 @@ $ bun add react-devtools-core@7 -d
|
|
|
1798
1799
|
AND a.ended_at IS NULL
|
|
1799
1800
|
ORDER BY a.started_at DESC
|
|
1800
1801
|
`).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 execSync13}from"child_process";function execQuiet(cmd){try{return execSync13(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(`
|
|
1801
|
-
`)){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]),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:execSync14}=await import("child_process");execSync14(`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(`
|
|
1802
|
+
`)){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:execSync14}=await import("child_process");execSync14(`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(`
|
|
1802
1803
|
`)[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(`
|
|
1803
1804
|
`)[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(`
|
|
1804
1805
|
\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.4",
|
|
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"
|
|
@@ -96,6 +96,17 @@ export function Nav({ tree, onTreeChange, onProjectSelect }: NavProps) {
|
|
|
96
96
|
[activeTab],
|
|
97
97
|
);
|
|
98
98
|
|
|
99
|
+
// Auto-switch right pane when cursor lands on a project node
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (activeTab !== 'projects' || tabBarFocused) return;
|
|
102
|
+
const current = flatNodes[projectIndex]?.node;
|
|
103
|
+
if (!current || current.type !== 'project') return;
|
|
104
|
+
const proj = current.data as { id: string; tmuxSession: string | null };
|
|
105
|
+
if (proj.tmuxSession) {
|
|
106
|
+
onProjectSelect(proj.id, proj.tmuxSession);
|
|
107
|
+
}
|
|
108
|
+
}, [activeTab, tabBarFocused, projectIndex, flatNodes, onProjectSelect]);
|
|
109
|
+
|
|
99
110
|
const handleProjectSelect = useCallback(
|
|
100
111
|
(id: string) => {
|
|
101
112
|
const idx = flatNodes.findIndex((n) => n.node.id === id);
|
package/src/tui/tmux.ts
CHANGED
|
@@ -49,21 +49,55 @@ export function createTuiSession(): { session: string; leftPane: string; rightPa
|
|
|
49
49
|
return { session: SESSION_NAME, leftPane, rightPane };
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the right pane ID — self-healing if the pane was killed/recreated.
|
|
54
|
+
* Falls back to re-discovering from the session layout.
|
|
55
|
+
*/
|
|
56
|
+
function resolveRightPane(rightPane: string): string {
|
|
57
|
+
try {
|
|
58
|
+
execSync(`tmux display-message -t ${rightPane} -p ''`, { stdio: 'ignore' });
|
|
59
|
+
return rightPane;
|
|
60
|
+
} catch {
|
|
61
|
+
try {
|
|
62
|
+
const panes = execSync(`tmux list-panes -t ${SESSION_NAME}:0 -F '#{pane_id}'`, { encoding: 'utf-8' })
|
|
63
|
+
.trim()
|
|
64
|
+
.split('\n');
|
|
65
|
+
return panes[1] || panes[0];
|
|
66
|
+
} catch {
|
|
67
|
+
return rightPane;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Ensure a tmux session exists, creating it if needed */
|
|
73
|
+
function ensureSession(sessionName: string): void {
|
|
74
|
+
try {
|
|
75
|
+
execSync(`tmux has-session -t '${sessionName}' 2>/dev/null`, { stdio: 'ignore' });
|
|
76
|
+
} catch {
|
|
77
|
+
try {
|
|
78
|
+
execSync(`tmux new-session -d -s '${sessionName}'`, { stdio: 'ignore' });
|
|
79
|
+
} catch {
|
|
80
|
+
// race: another process created it
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
52
85
|
/** Attach a project's tmux session in the right pane (nested) */
|
|
53
86
|
export function attachProject(rightPane: string, targetSession: string): void {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
87
|
+
const pane = resolveRightPane(rightPane);
|
|
88
|
+
ensureSession(targetSession);
|
|
89
|
+
try {
|
|
90
|
+
execSync(`tmux respawn-pane -k -t ${pane} "TMUX='' tmux attach-session -t '${targetSession}'"`, {
|
|
91
|
+
stdio: 'ignore',
|
|
92
|
+
});
|
|
93
|
+
} catch {
|
|
94
|
+
// pane doesn't exist
|
|
95
|
+
}
|
|
58
96
|
}
|
|
59
97
|
|
|
60
98
|
/** Switch right pane to a different project session */
|
|
61
99
|
export function switchRightPane(rightPane: string, targetSession: string): void {
|
|
62
|
-
|
|
63
|
-
execSync(`tmux send-keys -t ${rightPane} "" Enter`, { stdio: 'ignore' });
|
|
64
|
-
setTimeout(() => {
|
|
65
|
-
attachProject(rightPane, targetSession);
|
|
66
|
-
}, 100);
|
|
100
|
+
attachProject(rightPane, targetSession);
|
|
67
101
|
}
|
|
68
102
|
|
|
69
103
|
/**
|