@automagik/genie 4.260331.2 → 4.260331.3

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/dist/genie.js CHANGED
@@ -263,7 +263,7 @@ ${content}`;if(params.extraArgs){let fileIdx=params.extraArgs.indexOf("--append-
263
263
 
264
264
  ${readFileSync7(params.extraArgs[fileIdx+1],"utf-8")}`,params.extraArgs.splice(fileIdx,2)}writeFileSync6(promptFile,content);let flag=params.promptMode==="system"?"--system-prompt-file":"--append-system-prompt-file";parts.push(flag,escapeShellArg(promptFile))}else if(params.systemPromptFile){let flag=params.promptMode==="system"?"--system-prompt-file":"--append-system-prompt-file";parts.push(flag,escapeShellArg(params.systemPromptFile))}}function appendOtelEnv(env,params){if(!params.otelPort||process.env.OTEL_EXPORTER_OTLP_ENDPOINT)return;if(env.CLAUDE_CODE_ENABLE_TELEMETRY="1",env.OTEL_LOGS_EXPORTER="otlp",env.OTEL_METRICS_EXPORTER="otlp",env.OTEL_EXPORTER_OTLP_PROTOCOL="http/json",env.OTEL_EXPORTER_OTLP_ENDPOINT=`http://127.0.0.1:${params.otelPort}`,env.OTEL_LOG_TOOL_DETAILS="1",params.otelLogPrompts!==!1)env.OTEL_LOG_USER_PROMPTS="1";let resourceParts=[];if(params.role)resourceParts.push(`agent.name=${params.role}`);if(params.team)resourceParts.push(`team.name=${params.team}`);if(params.otelWishSlug)resourceParts.push(`wish.slug=${params.otelWishSlug}`);if(params.role)resourceParts.push(`agent.role=${params.role}`);if(resourceParts.length>0)env.OTEL_RESOURCE_ATTRIBUTES=resourceParts.join(",")}function buildClaudeCommand(params){preflightCheck("claude");let parts=[resolveShellBinary("claude")??"claude","--dangerously-skip-permissions"],env={};if(env.GENIE_WORKER="1",params.role)env.GENIE_AGENT_NAME=params.role;if(params.team)env.GENIE_TEAM=params.team;if(appendOtelEnv(env,params),params.nativeTeam?.enabled)appendNativeTeamFlags(parts,env,params.nativeTeam,params);if(params.resume)parts.push("--resume",escapeShellArg(params.resume));else if(params.sessionId)parts.push("--session-id",escapeShellArg(params.sessionId));if(params.role)parts.push("--agent",escapeShellArg(params.role));if(params.model)parts.push("--model",escapeShellArg(params.model));if(params.name)parts.push("--name",escapeShellArg(params.name));if(appendSystemPromptFlags(parts,params),params.extraArgs)for(let arg of params.extraArgs)parts.push(escapeShellArg(arg));if(params.initialPrompt)parts.push(escapeShellArg(params.initialPrompt));return{command:parts.join(" "),provider:"claude",env:Object.keys(env).length>0?env:void 0,meta:{role:params.role,skill:params.skill}}}function buildCodexCommand(params){preflightCheck("codex");let parts=["codex"];if(parts.push("--yolo"),parts.push("--no-alt-screen"),params.extraArgs)for(let arg of params.extraArgs)parts.push(escapeShellArg(arg));let promptParts=[`Genie worker. Team: ${params.team}.`];if(params.role)promptParts.push(`Role: ${params.role}.`);if(params.skill)promptParts.push(`Execute the ${params.skill} skill instructions.`);let prompt2=promptParts.join(" ");return parts.push(escapeShellArg(prompt2)),{command:parts.join(" "),provider:"codex",meta:{role:params.role,skill:params.skill}}}function buildLaunchCommand(params){let validated=validateSpawnParams(params);switch(validated.provider){case"claude":return buildClaudeCommand(validated);case"codex":return buildCodexCommand(validated);default:throw Error(`Unknown provider "${validated.provider}". Valid providers: claude, codex`)}}var CLAUDE_TEAM_COLORS,spawnParamsSchema;var init_provider_adapters=__esm(()=>{init_zod();CLAUDE_TEAM_COLORS=["red","blue","green","yellow","purple","orange","pink","cyan"],spawnParamsSchema=exports_external.object({provider:exports_external.enum(["claude","codex"]),team:exports_external.string().min(1,"Team name is required"),role:exports_external.string().optional(),skill:exports_external.string().optional(),extraArgs:exports_external.array(exports_external.string()).optional(),nativeTeam:exports_external.object({enabled:exports_external.boolean(),parentSessionId:exports_external.string().optional(),color:exports_external.string().optional(),agentType:exports_external.string().optional(),planModeRequired:exports_external.boolean().optional(),permissionMode:exports_external.string().optional(),agentName:exports_external.string().optional()}).optional(),sessionId:exports_external.string().uuid().optional(),resume:exports_external.string().optional(),systemPromptFile:exports_external.string().optional(),systemPrompt:exports_external.string().optional(),promptMode:exports_external.enum(["system","append"]).optional(),model:exports_external.string().optional(),initialPrompt:exports_external.string().optional(),name:exports_external.string().optional(),otelPort:exports_external.number().optional(),otelLogPrompts:exports_external.boolean().optional(),otelWishSlug:exports_external.string().optional()})});var exports_claude_native_teams={};__export(exports_claude_native_teams,{writeNativeInbox:()=>writeNativeInbox,unregisterNativeMember:()=>unregisterNativeMember,sanitizeTeamName:()=>sanitizeTeamName,resolveNativeMemberName:()=>resolveNativeMemberName,registerNativeMember:()=>registerNativeMember,registerAsTeamLead:()=>registerAsTeamLead,loadConfig:()=>loadConfig,listTeamsWithUnreadInbox:()=>listTeamsWithUnreadInbox,listTeams:()=>listTeams,isInsideClaudeCode:()=>isInsideClaudeCode,ensureNativeTeam:()=>ensureNativeTeam,discoverTeamName:()=>discoverTeamName,discoverClaudeParentSessionId:()=>discoverClaudeParentSessionId,deleteNativeTeam:()=>deleteNativeTeam,clearNativeInbox:()=>clearNativeInbox,assignColor:()=>assignColor});import{existsSync as existsSync12}from"fs";import{mkdir as mkdir2,open,readFile as readFile2,readdir as readdir2,rm,stat,unlink as unlink2,writeFile}from"fs/promises";import{homedir as homedir12}from"os";import{join as join13}from"path";function claudeConfigDir(){return process.env.CLAUDE_CONFIG_DIR??join13(homedir12(),".claude")}function teamsBaseDir(){return join13(claudeConfigDir(),"teams")}function sanitizeTeamName(name){return name.replace(/[^a-zA-Z0-9]/g,"-").toLowerCase()}async function listTeams(){try{return(await readdir2(teamsBaseDir())).filter((e)=>!e.startsWith("."))}catch{return[]}}function teamDir(teamName){return join13(teamsBaseDir(),sanitizeTeamName(teamName))}function configPath(teamName){return join13(teamDir(teamName),"config.json")}function inboxesDir(teamName){return join13(teamDir(teamName),"inboxes")}function inboxPath(teamName,agentName){return join13(inboxesDir(teamName),`${sanitizeTeamName(agentName)}.json`)}function lockPath(filePath){return`${filePath}.lock`}async function acquireLock(path){let lock=lockPath(path),deadline=Date.now()+LOCK_TIMEOUT_MS;while(Date.now()<deadline)try{await writeFile(lock,String(process.pid),{flag:"wx"});return}catch{let jitter=Math.floor(Math.random()*LOCK_POLL_MS);await new Promise((r)=>setTimeout(r,LOCK_POLL_MS+jitter))}console.warn(`[claude-native-teams] Force-acquiring stale lock: ${lock}`),await writeFile(lock,String(process.pid))}async function releaseLock(path){try{await unlink2(lockPath(path))}catch{}}async function loadConfig(teamName){try{let content=await readFile2(configPath(teamName),"utf-8");return JSON.parse(content)}catch(err){if(err instanceof Error&&"code"in err&&err.code==="ENOENT")return null;let message=err instanceof Error?err.message:String(err);return console.warn(`[claude-native-teams] Failed to load config for "${teamName}": ${message}`),null}}async function saveConfig(teamName,config){await writeFile(configPath(teamName),JSON.stringify(config,null,2))}async function countLeadSessionRefs(){let counts=new Map,teams=await listTeams();for(let team of teams){let leadSessionId=(await loadConfig(team))?.leadSessionId;if(!leadSessionId)continue;counts.set(leadSessionId,(counts.get(leadSessionId)??0)+1)}return counts}async function ensureNativeTeam(teamName,description,leadSessionId){let dir=teamDir(teamName),inboxDir=inboxesDir(teamName);await mkdir2(dir,{recursive:!0}),await mkdir2(inboxDir,{recursive:!0});let existing=await loadConfig(teamName);if(existing)return existing;let sanitized=sanitizeTeamName(teamName),config={name:sanitized,description,createdAt:Date.now(),leadAgentId:`team-lead@${sanitized}`,leadSessionId,members:[]};return await saveConfig(teamName,config),config}async function registerNativeMember(teamName,member){let config=await loadConfig(teamName);if(!config)throw Error(`Native team "${teamName}" not found`);let sanitized=sanitizeTeamName(teamName),agentId=`${sanitizeTeamName(member.agentName)}@${sanitized}`;config.members=config.members.filter((m)=>m.agentId!==agentId),config.members.push({agentId,name:sanitizeTeamName(member.agentName),agentType:member.agentType??"general-purpose",joinedAt:Date.now(),tmuxPaneId:member.tmuxPaneId,cwd:member.cwd??process.cwd(),backendType:"tmux",color:member.color,planModeRequired:member.planModeRequired??!1,isActive:!0}),await saveConfig(teamName,config);let inbox=inboxPath(teamName,member.agentName);if(!existsSync12(inbox))await writeFile(inbox,"[]")}async function unregisterNativeMember(teamName,agentName){let config=await loadConfig(teamName);if(!config)return;let sanitized=sanitizeTeamName(teamName),agentId=`${sanitizeTeamName(agentName)}@${sanitized}`,member=config.members.find((m)=>m.agentId===agentId);if(member)member.isActive=!1;await saveConfig(teamName,config)}async function writeNativeInbox(teamName,agentName,message){let path=inboxPath(teamName,agentName);await mkdir2(inboxesDir(teamName),{recursive:!0}),await acquireLock(path);try{let messages2=[];try{let content=await readFile2(path,"utf-8");messages2=JSON.parse(content)}catch{}messages2.push(message),await writeFile(path,JSON.stringify(messages2,null,2))}finally{await releaseLock(path)}}async function resolveNativeMemberName(teamName,genieWorkerId){let config=await loadConfig(teamName);if(!config||config.members.length===0)return null;let sanitizedId=sanitizeTeamName(genieWorkerId),sanitizedTeam=sanitizeTeamName(teamName),exactMatch=config.members.find((m)=>m.name===sanitizedId&&m.isActive);if(exactMatch)return exactMatch.name;let agentIdMatch=config.members.find((m)=>m.agentId===`${sanitizedId}@${sanitizedTeam}`&&m.isActive);if(agentIdMatch)return agentIdMatch.name;let teamPrefix=`${sanitizedTeam}-`;if(sanitizedId.startsWith(teamPrefix)){let stripped=sanitizedId.slice(teamPrefix.length),prefixMatch=config.members.find((m)=>m.name===stripped&&m.isActive);if(prefixMatch)return prefixMatch.name}let inactiveMatch=config.members.find((m)=>m.name===sanitizedId);if(inactiveMatch)return inactiveMatch.name;return null}async function assignColor(teamName){let config=await loadConfig(teamName);if(!config)return CLAUDE_TEAM_COLORS[0];let usedColors=new Set(config.members.map((m)=>m.color));for(let color of CLAUDE_TEAM_COLORS)if(!usedColors.has(color))return color;return CLAUDE_TEAM_COLORS[config.members.length%CLAUDE_TEAM_COLORS.length]}async function clearNativeInbox(teamName,agentName){let path=inboxPath(teamName,agentName);await acquireLock(path);try{await writeFile(path,"[]")}finally{await releaseLock(path)}}async function deleteNativeTeam(teamName){let dir=teamDir(teamName);if(!existsSync12(dir))return!1;return await rm(dir,{recursive:!0,force:!0}),!0}async function listTeamsWithUnreadInbox(){let base=teamsBaseDir(),teamDirs;try{teamDirs=await readdir2(base)}catch{return[]}let results=[];for(let name of teamDirs){let inboxFile=join13(base,name,"inboxes","team-lead.json"),messages2;try{let content=await readFile2(inboxFile,"utf-8");messages2=JSON.parse(content)}catch{continue}if(!Array.isArray(messages2))continue;let unread=messages2.filter((m)=>m.read===!1);if(unread.length===0)continue;let workingDir=null;try{let cfgContent=await readFile2(join13(base,name,"config.json"),"utf-8"),leadMember=JSON.parse(cfgContent).members.find((m)=>m.name==="team-lead"||m.agentId.startsWith("team-lead@"));if(leadMember?.cwd)workingDir=leadMember.cwd}catch{}results.push({teamName:name,unreadCount:unread.length,workingDir,firstUnreadText:unread[0]?.text??null})}return results}function sanitizePath(p){return p.replace(/[^a-zA-Z0-9]/g,"-")}async function discoverClaudeSessionId(cwd){let envSessionId=process.env.CLAUDE_CODE_SESSION_ID;if(envSessionId)return envSessionId;let projectDir=join13(claudeConfigDir(),"projects",sanitizePath(cwd??process.cwd()));try{let jsonls=(await readdir2(projectDir)).filter((e)=>e.endsWith(".jsonl"));if(jsonls.length===0)return null;let newest=null;for(let name of jsonls){let s=await stat(join13(projectDir,name));if(!newest||s.mtimeMs>newest.mtime)newest={name,mtime:s.mtimeMs}}if(!newest)return null;return newest.name.replace(".jsonl","")}catch{return null}}async function readSessionMetadata(filePath){let handle=null;try{handle=await open(filePath,"r");let buffer2=Buffer.alloc(8192),{bytesRead}=await handle.read(buffer2,0,buffer2.length,0),head=buffer2.toString("utf-8",0,bytesRead);for(let line of head.split(`
265
265
  `).slice(0,20)){let trimmed=line.trim();if(!trimmed)continue;try{let entry=JSON.parse(trimmed),teamName=typeof entry.teamName==="string"?entry.teamName:void 0,agentName=typeof entry.agentName==="string"?entry.agentName:void 0;if(teamName||agentName)return{teamName,agentName}}catch{}}}catch{return{}}finally{await handle?.close().catch(()=>{})}return{}}function rootScore(metadata){if(!metadata.teamName&&!metadata.agentName)return 2;if(metadata.agentName==="team-lead")return 1;return 0}function compareSessionRanking(a,b2,leadRefs){let aLeadRefs=leadRefs.get(a.name.replace(".jsonl",""))??0,bLeadRefs=leadRefs.get(b2.name.replace(".jsonl",""))??0;if(aLeadRefs!==bLeadRefs)return bLeadRefs-aLeadRefs;let aRoot=rootScore(a.metadata),bRoot=rootScore(b2.metadata);if(aRoot!==bRoot)return bRoot-aRoot;return b2.mtime-a.mtime}async function discoverClaudeParentSessionId(cwd){let envSessionId=process.env.CLAUDE_CODE_SESSION_ID;if(envSessionId)return envSessionId;let projectDir=join13(claudeConfigDir(),"projects",sanitizePath(cwd??process.cwd()));try{let jsonls=(await readdir2(projectDir)).filter((e)=>e.endsWith(".jsonl"));if(jsonls.length===0)return null;let ranked=await Promise.all(jsonls.map(async(name)=>{let filePath=join13(projectDir,name),s=await stat(filePath),metadata=await readSessionMetadata(filePath);return{name,mtime:s.mtimeMs,metadata}})),leadRefs=await countLeadSessionRefs();return ranked.sort((a,b2)=>compareSessionRanking(a,b2,leadRefs)),ranked[0]?.name.replace(".jsonl","")??null}catch{return null}}function isInsideClaudeCode(){return process.env.CLAUDECODE==="1"}async function discoverTeamName(cwd){let envTeam=process.env.GENIE_TEAM;if(envTeam)return envTeam;let sessionId=await discoverClaudeSessionId(cwd);if(!sessionId)return null;let base=teamsBaseDir();try{let teams=await readdir2(base);for(let name of teams){let cfgPath=join13(base,name,"config.json");try{let content=await readFile2(cfgPath,"utf-8"),config=JSON.parse(content);if(config.leadSessionId===sessionId)return config.name}catch{}}}catch{}return null}async function registerAsTeamLead(teamName,opts){let sessionId=await discoverClaudeSessionId(opts?.cwd);if(!sessionId)throw Error("Could not discover Claude Code session ID. Are you running inside Claude Code with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1?");let config=await ensureNativeTeam(teamName,`Genie team: ${teamName}`,sessionId);if(config.leadSessionId!==sessionId)config.leadSessionId=sessionId,await saveConfig(teamName,config);let leadAgentId=`team-lead@${sanitizeTeamName(teamName)}`,existingLead=config.members.find((m)=>m.agentId===leadAgentId),resolvedPaneId=opts?.tmuxPaneId??process.env.TMUX_PANE;if(!existingLead||!existingLead.isActive)await registerNativeMember(teamName,{agentName:"team-lead",agentType:"general-purpose",color:opts?.color??"blue",tmuxPaneId:resolvedPaneId,cwd:opts?.cwd??process.cwd()});else if(resolvedPaneId&&existingLead.tmuxPaneId!==resolvedPaneId)existingLead.tmuxPaneId=resolvedPaneId,await saveConfig(teamName,config);let inbox=inboxPath(teamName,"team-lead");if(!existsSync12(inbox))await writeFile(inbox,"[]");let finalConfig=await loadConfig(teamName);if(!finalConfig)throw Error(`Failed to load config for team "${teamName}" after creation`);return{sessionId,config:finalConfig}}var LOCK_TIMEOUT_MS=5000,LOCK_POLL_MS=50;var init_claude_native_teams=__esm(()=>{init_provider_adapters()});var exports_team_lead_command={};__export(exports_team_lead_command,{shellQuote:()=>shellQuote,sessionExists:()=>sessionExists,ccProjectDirName:()=>ccProjectDirName,buildTeamLeadCommand:()=>buildTeamLeadCommand});import{readFileSync as readFileSync7,readdirSync as readdirSync3}from"fs";import{basename,join as join14}from"path";function shellQuote(s){return`'${s.replace(/'/g,"'\\''")}'`}function buildTeamLeadCommand(teamName,options){let sanitized=sanitizeTeamName(teamName),qTeam=shellQuote(sanitized),folderName=basename(process.cwd()),parts=["GENIE_WORKER=1","CLAUDECODE=1","CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1",`GENIE_TEAM=${qTeam}`,`GENIE_AGENT_NAME=${shellQuote(folderName)}`,"claude",`--agent-id ${shellQuote(`team-lead@${sanitized}`)}`,"--agent-name team-lead",`--team-name ${qTeam}`,"--agent-type team-lead","--dangerously-skip-permissions"];if(parts.push(`--name ${shellQuote(sanitized)}`),options?.continueName)parts.push(`--resume ${shellQuote(options.continueName)}`);else if(options?.sessionId)parts.push(`--session-id ${shellQuote(options.sessionId)}`);if(options?.systemPromptFile){let promptFlag=(options?.promptMode??loadGenieConfigSync().promptMode)==="system"?"--system-prompt-file":"--append-system-prompt-file";parts.push(`${promptFlag} ${shellQuote(options.systemPromptFile)}`)}return parts.join(" ")}function ccProjectDirName(dir){return dir.replace(/\//g,"-")}function fileHasSessionName(filePath,needle){try{let lines=readFileSync7(filePath,"utf-8").split(`
266
- `).slice(0,10);for(let line of lines){if(!line.includes("custom-title"))continue;let entry=JSON.parse(line);if(entry.type==="custom-title"&&entry.customTitle?.toLowerCase()===needle)return!0}}catch{}return!1}function sessionExists(name,cwd){try{let home=process.env.HOME??"/root",projectDir=ccProjectDirName(cwd??process.cwd()),projectPath=join14(home,".claude","projects",projectDir),files;try{files=readdirSync3(projectPath).filter((f)=>f.endsWith(".jsonl"))}catch{return!1}let needle=name.toLowerCase();return files.some((file)=>fileHasSessionName(join14(projectPath,file),needle))}catch{return!1}}var init_team_lead_command=__esm(()=>{init_claude_native_teams();init_genie_config2()});var exports_tmux_wrapper={};__export(exports_tmux_wrapper,{genieTmuxPrefix:()=>genieTmuxPrefix,genieTmuxCmd:()=>genieTmuxCmd,executeTmux:()=>executeTmux});import{exec as execCallback}from"child_process";import{existsSync as existsSync13,mkdirSync as mkdirSync6}from"fs";import{homedir as homedir13}from"os";import{join as join15}from"path";import{promisify}from"util";function resolveGenieTmuxConf(){let home=homedir13(),genieHome=process.env.GENIE_HOME??join15(home,".genie");return[join15(genieHome,"tmux.conf"),join15(__dirname,"..","..","scripts","tmux","genie.tmux.conf")].find((p)=>existsSync13(p))??"/dev/null"}function genieTmuxPrefix(){return["-L",GENIE_TMUX_SOCKET,"-f",resolveGenieTmuxConf()]}function genieTmuxCmd(subcommand){return`tmux ${genieTmuxPrefix().join(" ")} ${subcommand}`}function getLogDir(){let logDir=join15(homedir13(),".genie","logs","tmux");if(!existsSync13(logDir))mkdirSync6(logDir,{recursive:!0});return logDir}function stripVerboseFlags(args){return args.filter((arg)=>!/^-v+$/.test(arg))}function isTmuxDebugEnabled(){return process.env.GENIE_TMUX_DEBUG==="1"}async function executeTmux(args){let argList=typeof args==="string"?args.split(/\s+/).filter(Boolean):args,finalArgs=stripVerboseFlags(argList),debugMode=isTmuxDebugEnabled(),options={};if(debugMode)finalArgs=["-v",...finalArgs],options.cwd=getLogDir();finalArgs=[...genieTmuxPrefix(),...finalArgs];let command=`tmux ${finalArgs.join(" ")}`,{stdout}=await exec(command,options);return stdout.trim()}var __dirname="/home/runner/_work/genie/genie/src/lib",exec,GENIE_TMUX_SOCKET;var init_tmux_wrapper=__esm(()=>{exec=promisify(execCallback),GENIE_TMUX_SOCKET=process.env.GENIE_TMUX_SOCKET||"genie"});var exports_tmux={};__export(exports_tmux,{setWindowEnv:()=>setWindowEnv,listWindows:()=>listWindows,listPanes:()=>listPanes,killSession:()=>killSession,isPaneAlive:()=>isPaneAlive,getWindowEnv:()=>getWindowEnv,getCurrentSessionName:()=>getCurrentSessionName,findWindowByName:()=>findWindowByName,findSessionByName:()=>findSessionByName,executeTmux:()=>executeTmux2,ensureTeamWindow:()=>ensureTeamWindow,createSession:()=>createSession,capturePaneContent:()=>capturePaneContent,applyPaneColor:()=>applyPaneColor});async function executeTmux2(tmuxCommand){try{return await executeTmux(tmuxCommand)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);throw Error(`Failed to execute tmux command: ${message}`)}}async function getCurrentSessionName(hint){if(process.env.TMUX)try{return(await executeTmux2("display-message -p '#{session_name}'")).trim()||null}catch{return null}try{let sessions=await listSessions();if(sessions.length===0)return null;if(hint){let match=sessions.find((s)=>s.name.includes(hint));if(match)return match.name}return sessions[0].name}catch{return null}}async function listSessions(){try{let output=await executeTmux2("list-sessions -F '#{session_id}:#{session_name}:#{?session_attached,1,0}:#{session_windows}'");if(!output)return[];return output.split(`
266
+ `).slice(0,10);for(let line of lines){if(!line.includes("custom-title"))continue;let entry=JSON.parse(line);if(entry.type==="custom-title"&&entry.customTitle?.toLowerCase()===needle)return!0}}catch{}return!1}function sessionExists(name,cwd){try{let home=process.env.HOME??"/root",projectDir=ccProjectDirName(cwd??process.cwd()),projectPath=join14(home,".claude","projects",projectDir),files;try{files=readdirSync3(projectPath).filter((f)=>f.endsWith(".jsonl"))}catch{return!1}let needle=name.toLowerCase();return files.some((file)=>fileHasSessionName(join14(projectPath,file),needle))}catch{return!1}}var init_team_lead_command=__esm(()=>{init_claude_native_teams();init_genie_config2()});var exports_tmux_wrapper={};__export(exports_tmux_wrapper,{genieTmuxPrefix:()=>genieTmuxPrefix,genieTmuxCmd:()=>genieTmuxCmd,executeTmux:()=>executeTmux});import{exec as execCallback}from"child_process";import{existsSync as existsSync13,mkdirSync as mkdirSync6}from"fs";import{homedir as homedir13}from"os";import{join as join15}from"path";import{promisify}from"util";function resolveGenieTmuxConf(){let home=homedir13(),genieHome=process.env.GENIE_HOME??join15(home,".genie");return[join15(genieHome,"tmux.conf"),join15(__dirname,"..","..","scripts","tmux","genie.tmux.conf")].find((p)=>existsSync13(p))??"/dev/null"}function genieTmuxPrefix(){return["-L",GENIE_TMUX_SOCKET,"-f",resolveGenieTmuxConf()]}function genieTmuxCmd(subcommand){return`tmux ${genieTmuxPrefix().join(" ")} ${subcommand}`}function getLogDir(){let logDir=join15(homedir13(),".genie","logs","tmux");if(!existsSync13(logDir))mkdirSync6(logDir,{recursive:!0});return logDir}function stripVerboseFlags(args){return args.filter((arg)=>!/^-v+$/.test(arg))}function isTmuxDebugEnabled(){return process.env.GENIE_TMUX_DEBUG==="1"}async function executeTmux(args){let argList=typeof args==="string"?args.split(/\s+/).filter(Boolean):args,finalArgs=stripVerboseFlags(argList),debugMode=isTmuxDebugEnabled(),options={};if(debugMode)finalArgs=["-v",...finalArgs],options.cwd=getLogDir();finalArgs=[...genieTmuxPrefix(),...finalArgs];let command=`tmux ${finalArgs.join(" ")}`,{stdout}=await exec(command,options);return stdout.trim()}var __dirname="/home/runner/_work/genie/genie/src/lib",exec,GENIE_TMUX_SOCKET;var init_tmux_wrapper=__esm(()=>{exec=promisify(execCallback),GENIE_TMUX_SOCKET=process.env.GENIE_TMUX_SOCKET||"genie"});var exports_tmux={};__export(exports_tmux,{setWindowEnv:()=>setWindowEnv,resolveRepoSession:()=>resolveRepoSession,listWindows:()=>listWindows,listPanes:()=>listPanes,killWindow:()=>killWindow,killSession:()=>killSession,isPaneAlive:()=>isPaneAlive,getWindowEnv:()=>getWindowEnv,getCurrentSessionName:()=>getCurrentSessionName,findWindowByName:()=>findWindowByName,findSessionByName:()=>findSessionByName,executeTmux:()=>executeTmux2,ensureTeamWindow:()=>ensureTeamWindow,createSession:()=>createSession,capturePaneContent:()=>capturePaneContent,applyPaneColor:()=>applyPaneColor});import{basename as basename2}from"path";async function executeTmux2(tmuxCommand){try{return await executeTmux(tmuxCommand)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);throw Error(`Failed to execute tmux command: ${message}`)}}async function getCurrentSessionName(hint){if(process.env.TMUX)try{return(await executeTmux2("display-message -p '#{session_name}'")).trim()||null}catch{return null}try{let sessions=await listSessions();if(sessions.length===0)return null;if(hint){let match=sessions.find((s)=>s.name.includes(hint));if(match)return match.name}return sessions[0].name}catch{return null}}async function listSessions(){try{let output=await executeTmux2("list-sessions -F '#{session_id}:#{session_name}:#{?session_attached,1,0}:#{session_windows}'");if(!output)return[];return output.split(`
267
267
  `).map((line)=>{let[id,name,attached,windows]=line.split(":");return{id,name,attached:attached==="1",windows:Number.parseInt(windows,10)}})}catch(error2){if((error2 instanceof Error?error2.message:String(error2)).includes("no server running"))return[];throw error2}}async function findSessionByName(name){try{return(await listSessions()).find((session)=>session.name===name)||null}catch(_error){return null}}async function getWindowEnv(target,varName){try{let output=await executeTmux2(`show-environment -t ${shellQuote(target)} ${shellQuote(varName)}`),prefix=`${varName}=`;if(output?.startsWith(prefix))return output.slice(prefix.length).trim();return null}catch{return null}}async function setWindowEnv(target,varName,value){await executeTmux2(`set-environment -t ${shellQuote(target)} ${shellQuote(varName)} ${shellQuote(value)}`)}async function killSession(sessionId){await executeTmux2(`kill-session -t '${sessionId}'`)}async function listWindows(sessionId){try{let output=await executeTmux2(`list-windows -t '${sessionId}' -F '#{window_id}:#{window_name}:#{window_index}:#{?window_active,1,0}'`);if(!output)return[];return output.split(`
268
268
  `).map((line)=>{let[id,name,indexStr,active]=line.split(":");return{id,name,index:Number.parseInt(indexStr,10),active:active==="1",sessionId}})}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);if(message.includes("no server running")||message.includes("session not found"))return[];throw error2}}async function listPanes(windowId){try{let output=await executeTmux2(`list-panes -t '${windowId}' -F '#{pane_id}:#{pane_title}:#{?pane_active,1,0}'`);if(!output)return[];return output.split(`
269
269
  `).map((line)=>{let[id,title,active]=line.split(":");return{id,windowId,title,active:active==="1"}})}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);if(message.includes("no server running")||message.includes("window not found"))return[];throw error2}}async function capturePaneContent(paneId,lines=200,includeColors=!1){try{return await executeTmux2(`capture-pane -p ${includeColors?"-e":""} -t '${paneId}' -S -${lines} -E -`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);if(message.includes("no server running")||message.includes("pane not found"))return"";throw error2}}async function createSession(name){return await executeTmux2(`new-session -d -s "${name}" -e LC_ALL=C.UTF-8 -e LANG=C.UTF-8`),findSessionByName(name)}async function createWindow(sessionId,name,workingDir){let cdFlag=workingDir?` -c '${workingDir.replace(/'/g,"'\\''")}'`:"",output=await executeTmux2(`new-window -d -P -F '#{window_id}:#{window_index}' -t '${sessionId}:' -n '${name}'${cdFlag}`),[windowId,indexStr]=output.trim().split(":");if(!windowId)return null;try{await executeTmux2(`set-window-option -t '${windowId}' automatic-rename off`)}catch{}return{id:windowId,name,index:Number.parseInt(indexStr,10)||0,active:!1,sessionId}}async function findWindowByName(sessionId,name){return(await listWindows(sessionId)).find((w)=>w.name===name)||null}async function ensureMasterWindow(session,masterName){try{let windows=await listWindows(session);if(windows.length<2)return;let masterWindow=windows.find((w)=>w.name===masterName);if(!masterWindow)return;let minIndex=Math.min(...windows.map((w)=>w.index));if(masterWindow.index===minIndex)return;await executeTmux2(`swap-window -s '${session}:${masterWindow.index}' -t '${session}:${minIndex}'`)}catch{}}async function ensureTeamWindow(session,teamName,workingDir){if(!await findSessionByName(session))await createSession(session);let existing=await findWindowByName(session,teamName);if(existing){try{await executeTmux2(`set-window-option -t '${existing.id}' automatic-rename off`)}catch{}await rehydratePaneColorHook(existing.id);let panes2=await listPanes(existing.id),paneId2=panes2.length>0?panes2[0].id:`${session}:${teamName}.0`;return{windowId:existing.id,windowName:teamName,paneId:paneId2,created:!1}}let windowsBefore=await listWindows(session),masterBefore=windowsBefore.length>0?windowsBefore.reduce((a,b2)=>a.index<=b2.index?a:b2):null,newWindow=await createWindow(session,teamName,workingDir);if(!newWindow)throw Error(`Failed to create team window "${teamName}" in session "${session}"`);if(masterBefore)await ensureMasterWindow(session,masterBefore.name);await rehydratePaneColorHook(newWindow.id);let panes=await listPanes(newWindow.id),paneId=panes.length>0?panes[0].id:`${session}:${teamName}.0`;return{windowId:newWindow.id,windowName:teamName,paneId,created:!0}}function ensurePaneColorScript(){let{existsSync:existsSync14,writeFileSync:writeFileSync6,mkdirSync:mkdirSync7,chmodSync:chmodSync2}=__require("fs"),{dirname:dirname3}=__require("path");if(existsSync14(PANE_COLOR_SCRIPT))return;mkdirSync7(dirname3(PANE_COLOR_SCRIPT),{recursive:!0}),writeFileSync6(PANE_COLOR_SCRIPT,`#!/bin/bash
@@ -272,7 +272,7 @@ PANE_ID="$1"
272
272
  COLOR=$(tmux display-message -p -t "$PANE_ID" '#{@genie_color}' 2>/dev/null)
273
273
  [ -z "$COLOR" ] && COLOR="default"
274
274
  tmux set-option -w pane-active-border-style "fg=$COLOR"
275
- `),chmodSync2(PANE_COLOR_SCRIPT,493)}async function applyPaneColor(paneId,color,windowId){let hex=TMUX_COLOR_MAP[color]??TMUX_COLOR_MAP.blue;try{ensurePaneColorScript(),await executeTmux2(`set-option -p -t '${paneId}' @genie_color '${hex}'`);try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));await(await getConnection2())`UPDATE executors SET pane_color = ${hex} WHERE tmux_pane_id = ${paneId}`}catch{}if(windowId)await executeTmux2(`set-hook -w -t '${windowId}' pane-focus-in "run-shell '${PANE_COLOR_SCRIPT} #{pane_id}'"`)}catch{}}async function rehydratePaneColorHook(windowId){try{ensurePaneColorScript(),await executeTmux2(`set-hook -w -t '${windowId}' pane-focus-in "run-shell '${PANE_COLOR_SCRIPT} #{pane_id}'"`)}catch{}}async function isPaneAlive(paneId){if(!paneId||paneId==="inline")return!1;if(!/^%\d+$/.test(paneId))return!1;try{return await capturePaneContent(paneId,1),!0}catch{return!1}}var TMUX_COLOR_MAP,PANE_COLOR_SCRIPT;var init_tmux=__esm(()=>{init_team_lead_command();init_tmux_wrapper();TMUX_COLOR_MAP={red:"#b83030",blue:"#2a6cb8",green:"#20a050",yellow:"#b8a020",purple:"#7830b8",orange:"#b86820",pink:"#b83078",cyan:"#20a0a0"},PANE_COLOR_SCRIPT=`${__require("os").homedir()}/.genie/tmux-pane-color.sh`});var exports_js_yaml={};__export(exports_js_yaml,{types:()=>types3,safeLoadAll:()=>safeLoadAll,safeLoad:()=>safeLoad,safeDump:()=>safeDump,loadAll:()=>loadAll,load:()=>load2,dump:()=>dump,default:()=>jsYaml,YAMLException:()=>YAMLException,Type:()=>Type,Schema:()=>Schema,JSON_SCHEMA:()=>JSON_SCHEMA,FAILSAFE_SCHEMA:()=>FAILSAFE_SCHEMA,DEFAULT_SCHEMA:()=>DEFAULT_SCHEMA,CORE_SCHEMA:()=>CORE_SCHEMA});function isNothing(subject){return typeof subject>"u"||subject===null}function isObject(subject){return typeof subject==="object"&&subject!==null}function toArray(sequence){if(Array.isArray(sequence))return sequence;else if(isNothing(sequence))return[];return[sequence]}function extend(target,source){var index,length,key,sourceKeys;if(source){sourceKeys=Object.keys(source);for(index=0,length=sourceKeys.length;index<length;index+=1)key=sourceKeys[index],target[key]=source[key]}return target}function repeat(string,count){var result="",cycle;for(cycle=0;cycle<count;cycle+=1)result+=string;return result}function isNegativeZero(number){return number===0&&Number.NEGATIVE_INFINITY===1/number}function formatError(exception,compact){var where="",message=exception.reason||"(unknown reason)";if(!exception.mark)return message;if(exception.mark.name)where+='in "'+exception.mark.name+'" ';if(where+="("+(exception.mark.line+1)+":"+(exception.mark.column+1)+")",!compact&&exception.mark.snippet)where+=`
275
+ `),chmodSync2(PANE_COLOR_SCRIPT,493)}async function applyPaneColor(paneId,color,windowId){let hex=TMUX_COLOR_MAP[color]??TMUX_COLOR_MAP.blue;try{ensurePaneColorScript(),await executeTmux2(`set-option -p -t '${paneId}' @genie_color '${hex}'`);try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));await(await getConnection2())`UPDATE executors SET pane_color = ${hex} WHERE tmux_pane_id = ${paneId}`}catch{}if(windowId)await executeTmux2(`set-hook -w -t '${windowId}' pane-focus-in "run-shell '${PANE_COLOR_SCRIPT} #{pane_id}'"`)}catch{}}async function rehydratePaneColorHook(windowId){try{ensurePaneColorScript(),await executeTmux2(`set-hook -w -t '${windowId}' pane-focus-in "run-shell '${PANE_COLOR_SCRIPT} #{pane_id}'"`)}catch{}}async function resolveRepoSession(repoPath){let derived=basename2(repoPath);try{let sessions=await listSessions(),exact=sessions.find((s)=>s.name===derived);if(exact)return exact.name;if(process.env.TMUX)try{let name=(await executeTmux2("display-message -p '#{session_name}'")).trim();if(name)return name}catch{}let partial=sessions.find((s)=>s.name.includes(derived));if(partial)return partial.name}catch{}return derived}async function isPaneAlive(paneId){if(!paneId||paneId==="inline")return!1;if(!/^%\d+$/.test(paneId))return!1;try{return await capturePaneContent(paneId,1),!0}catch{return!1}}async function killWindow(sessionName,windowName){try{return await executeTmux2(`kill-window -t ${shellQuote(`${sessionName}:${windowName}`)}`),!0}catch{return!1}}var TMUX_COLOR_MAP,PANE_COLOR_SCRIPT;var init_tmux=__esm(()=>{init_team_lead_command();init_tmux_wrapper();TMUX_COLOR_MAP={red:"#b83030",blue:"#2a6cb8",green:"#20a050",yellow:"#b8a020",purple:"#7830b8",orange:"#b86820",pink:"#b83078",cyan:"#20a0a0"},PANE_COLOR_SCRIPT=`${__require("os").homedir()}/.genie/tmux-pane-color.sh`});var exports_js_yaml={};__export(exports_js_yaml,{types:()=>types3,safeLoadAll:()=>safeLoadAll,safeLoad:()=>safeLoad,safeDump:()=>safeDump,loadAll:()=>loadAll,load:()=>load2,dump:()=>dump,default:()=>jsYaml,YAMLException:()=>YAMLException,Type:()=>Type,Schema:()=>Schema,JSON_SCHEMA:()=>JSON_SCHEMA,FAILSAFE_SCHEMA:()=>FAILSAFE_SCHEMA,DEFAULT_SCHEMA:()=>DEFAULT_SCHEMA,CORE_SCHEMA:()=>CORE_SCHEMA});function isNothing(subject){return typeof subject>"u"||subject===null}function isObject(subject){return typeof subject==="object"&&subject!==null}function toArray(sequence){if(Array.isArray(sequence))return sequence;else if(isNothing(sequence))return[];return[sequence]}function extend(target,source){var index,length,key,sourceKeys;if(source){sourceKeys=Object.keys(source);for(index=0,length=sourceKeys.length;index<length;index+=1)key=sourceKeys[index],target[key]=source[key]}return target}function repeat(string,count){var result="",cycle;for(cycle=0;cycle<count;cycle+=1)result+=string;return result}function isNegativeZero(number){return number===0&&Number.NEGATIVE_INFINITY===1/number}function formatError(exception,compact){var where="",message=exception.reason||"(unknown reason)";if(!exception.mark)return message;if(exception.mark.name)where+='in "'+exception.mark.name+'" ';if(where+="("+(exception.mark.line+1)+":"+(exception.mark.column+1)+")",!compact&&exception.mark.snippet)where+=`
276
276
 
277
277
  `+exception.mark.snippet;return message+" "+where}function YAMLException$1(reason,mark){if(Error.call(this),this.name="YAMLException",this.reason=reason,this.mark=mark,this.message=formatError(this,!1),Error.captureStackTrace)Error.captureStackTrace(this,this.constructor);else this.stack=Error().stack||""}function getLine(buffer2,lineStart,lineEnd,position,maxLineLength){var head="",tail="",maxHalfLength=Math.floor(maxLineLength/2)-1;if(position-lineStart>maxHalfLength)head=" ... ",lineStart=position-maxHalfLength+head.length;if(lineEnd-position>maxHalfLength)tail=" ...",lineEnd=position+maxHalfLength-tail.length;return{str:head+buffer2.slice(lineStart,lineEnd).replace(/\t/g,"\u2192")+tail,pos:position-lineStart+head.length}}function padStart(string,max){return common2.repeat(" ",max-string.length)+string}function makeSnippet(mark,options){if(options=Object.create(options||null),!mark.buffer)return null;if(!options.maxLength)options.maxLength=79;if(typeof options.indent!=="number")options.indent=1;if(typeof options.linesBefore!=="number")options.linesBefore=3;if(typeof options.linesAfter!=="number")options.linesAfter=2;var re=/\r?\n|\r|\0/g,lineStarts=[0],lineEnds=[],match,foundLineNo=-1;while(match=re.exec(mark.buffer))if(lineEnds.push(match.index),lineStarts.push(match.index+match[0].length),mark.position<=match.index&&foundLineNo<0)foundLineNo=lineStarts.length-2;if(foundLineNo<0)foundLineNo=lineStarts.length-1;var result="",i,line,lineNoLength=Math.min(mark.line+options.linesAfter,lineEnds.length).toString().length,maxLineLength=options.maxLength-(options.indent+lineNoLength+3);for(i=1;i<=options.linesBefore;i++){if(foundLineNo-i<0)break;line=getLine(mark.buffer,lineStarts[foundLineNo-i],lineEnds[foundLineNo-i],mark.position-(lineStarts[foundLineNo]-lineStarts[foundLineNo-i]),maxLineLength),result=common2.repeat(" ",options.indent)+padStart((mark.line-i+1).toString(),lineNoLength)+" | "+line.str+`
278
278
  `+result}line=getLine(mark.buffer,lineStarts[foundLineNo],lineEnds[foundLineNo],mark.position,maxLineLength),result+=common2.repeat(" ",options.indent)+padStart((mark.line+1).toString(),lineNoLength)+" | "+line.str+`
@@ -551,7 +551,7 @@ tmux set-option -w pane-active-border-style "fg=$COLOR"
551
551
  `}async function getTeam2(name){try{let rows=await(await getConnection())`SELECT * FROM teams WHERE name = ${name}`;if(rows.length===0)return null;return rowToTeamConfig(rows[0])}catch{return null}}async function listTeams2(includeArchived=!1){try{let sql=await getConnection();if(includeArchived)return(await sql`SELECT * FROM teams ORDER BY created_at DESC`).map(rowToTeamConfig);return(await sql`SELECT * FROM teams WHERE status != 'archived' ORDER BY created_at DESC`).map(rowToTeamConfig)}catch{return[]}}async function listMembers(teamName){let config=await getTeam2(teamName);if(!config)return null;return config.members}async function killTeamMembers(teamName){let config=await getTeam2(teamName);if(!config)return;for(let member of config.members)try{await killWorkersByName(member,teamName)}catch{}}async function setTeamStatus(teamName,status){if((await(await getConnection())`
552
552
  UPDATE teams SET status = ${status}
553
553
  WHERE name = ${teamName}
554
- `).count===0)throw Error(`Team "${teamName}" not found.`)}var init_team_manager=__esm(()=>{init_agent_registry();init_audit();init_builtin_agents();init_claude_native_teams();init_db();init_executor_registry();init_genie_config2();init_tmux()});var exports_protocol_router_spawn={};__export(exports_protocol_router_spawn,{spawnWorkerFromTemplate:()=>spawnWorkerFromTemplate,injectResumeContext:()=>injectResumeContext});import{exec as exec2}from"child_process";import{readFile as readFile4}from"fs/promises";import{join as join20}from"path";import{promisify as promisify2}from"util";async function resolveParentSession(_repoPath,team){let teamConfig=await getTeam2(team);if(teamConfig?.nativeTeamParentSessionId)return teamConfig.nativeTeamParentSessionId;return await discoverClaudeParentSessionId()??`genie-${team}`}function buildSpawnParams(template,parentSessionId,spawnColor,resumeSessionId){let isClaude=template.provider==="claude",sessionName=template.role?`${template.team}-${template.role}`:void 0,newSessionId=isClaude&&!resumeSessionId?crypto.randomUUID():void 0,params={provider:template.provider,team:template.team,role:template.role,skill:template.skill,extraArgs:template.extraArgs,sessionId:newSessionId,resume:isClaude?resumeSessionId:void 0,name:sessionName};if(isClaude)params.nativeTeam={enabled:!0,parentSessionId,color:spawnColor,agentType:template.role??"general-purpose",agentName:template.role};return params}function buildFullCommand(launch){if(launch.env&&Object.keys(launch.env).length>0)return`env ${Object.entries(launch.env).map(([k,v])=>`${k}=${v}`).join(" ")} ${launch.command}`;return launch.command}async function generateWorkerId(team,role){let base=role?`${team}-${role}`:team;return(await list()).some((w)=>w.id===base)?`${base}-${crypto.randomUUID().slice(0,8)}`:base}async function createExecutorForAutoSpawn(template,paneId,session,repoPath,effectiveSessionId,spawnColor,teamWindow){let agentName=template.role??"worker",agentIdentity=await findOrCreateAgent(agentName,template.team,template.role),currentExec=await getCurrentExecutor(agentIdentity.id);if(currentExec&&currentExec.state!=="terminated"&&currentExec.state!=="done"){let providerImpl=getProvider(currentExec.provider);if(providerImpl)try{await providerImpl.terminate(currentExec)}catch{}await terminateActiveExecutor(agentIdentity.id)}let pid=null;try{let{stdout:pidOut}=await execAsync(genieTmuxCmd(`display -t '${paneId}' -p '#{pane_pid}'`)),parsed=Number.parseInt(pidOut.trim(),10);if(parsed>0)pid=parsed}catch{}let executorTransport=template.provider==="codex"?"api":"tmux",executor=await createExecutor(agentIdentity.id,template.provider,executorTransport,{pid,tmuxSession:session,tmuxPaneId:paneId,tmuxWindow:teamWindow?.windowName??null,tmuxWindowId:teamWindow?.windowId??null,claudeSessionId:effectiveSessionId??null,state:"spawning",repoPath,paneColor:spawnColor??null});await setCurrentExecutor(agentIdentity.id,executor.id)}async function spawnPaneInSession(session,team,repoPath,fullCommand){let teamWindow=null;try{teamWindow=await ensureTeamWindow(session,team,repoPath)}catch{}let splitTarget=teamWindow?`-t '${teamWindow.windowId}'`:"",escapedCmd=fullCommand.replace(/'/g,"'\\''"),{stdout}=await execAsync(genieTmuxCmd(`split-window -d ${splitTarget} -P -F '#{pane_id}' '${escapedCmd}'`)),paneId=stdout.trim(),layoutTarget=`${session}:${teamWindow?.windowName??""}`;if(!teamWindow){let wins=await listWindows(session);layoutTarget=wins[0]?wins[0].id:`${session}:`}try{await execAsync(genieTmuxCmd(buildLayoutCommand(layoutTarget,resolveLayoutMode())))}catch{}return{paneId,teamWindow}}async function spawnWorkerFromTemplate(template,resumeSessionId){let repoPath=template.cwd??process.cwd(),team=template.team,parentSessionId=await resolveParentSession(repoPath,team);await ensureNativeTeam(team,`Genie team: ${team}`,parentSessionId);let spawnColor=await assignColor(team),params=buildSpawnParams(template,parentSessionId,spawnColor,resumeSessionId),launch=buildLaunchCommand(validateSpawnParams(params)),fullCommand=buildFullCommand(launch),workerId=await generateWorkerId(team,template.role),session=await getCurrentSessionName()??team,{paneId,teamWindow}=await spawnPaneInSession(session,team,repoPath,fullCommand),now=new Date().toISOString(),agentName=template.role??"worker",isClaude=template.provider==="claude",effectiveSessionId=resumeSessionId??params.sessionId,workerEntry={id:workerId,paneId,session,provider:template.provider,transport:"tmux",role:template.role,skill:template.skill,team,worktree:null,startedAt:now,state:"spawning",lastStateChange:now,repoPath,claudeSessionId:effectiveSessionId,nativeTeamEnabled:isClaude,nativeAgentId:`${agentName}@${team}`,nativeColor:spawnColor,parentSessionId,window:teamWindow?.windowName,windowName:teamWindow?.windowName,windowId:teamWindow?.windowId};await register(workerEntry);try{await createExecutorForAutoSpawn(template,paneId,session,repoPath,effectiveSessionId,spawnColor,teamWindow)}catch{}if(isClaude)await registerNativeMember(team,{agentName,agentType:template.role??"general-purpose",color:spawnColor??"blue",tmuxPaneId:paneId,cwd:repoPath}),await writeNativeInbox(team,"team-lead",{from:agentName,text:`Worker ${agentName} (${template.provider}) auto-spawned${resumeSessionId?" with --resume":""}. Ready for tasks.`,summary:`${agentName} auto-spawned`,timestamp:now,color:spawnColor??"blue",read:!1});if(spawnColor)await applyPaneColor(paneId,spawnColor,teamWindow?.windowId);return await injectResumeContext(repoPath,workerId,agentName,team),{worker:workerEntry,paneId,workerId}}function extractGroupSection(content,groupName){let escaped=groupName.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),pattern=new RegExp(`^### Group ${escaped}:`,"m"),match=content.match(pattern);if(!match||match.index===void 0)return null;let start=match.index,nextBoundary=content.slice(start).slice(1).search(/^### Group \d|^---$/m),end=nextBoundary!==-1?start+1+nextBoundary:content.length;return content.slice(start,end).trim()}async function getRecentGitLog(repoPath,count=3){try{let{stdout}=await execAsync(`git -C '${repoPath}' log --oneline -${count} 2>/dev/null`);return stdout.trim()}catch{return""}}async function getGitStatus(repoPath){try{let{stdout}=await execAsync(`git -C '${repoPath}' status --short 2>/dev/null`);return stdout.trim()}catch{return""}}async function injectResumeContext(repoPath,workerId,agentName,_team){try{let match=await findAnyGroupByAssignee(workerId,repoPath)??await findAnyGroupByAssignee(agentName,repoPath);if(!match)return;let{slug,groupName,group}=match,wishPath=join20(repoPath,".genie","wishes",slug,"WISH.md"),groupSection="";try{let wishContent=await readFile4(wishPath,"utf-8");groupSection=extractGroupSection(wishContent,groupName)??""}catch{}let gitLog=await getRecentGitLog(repoPath),gitStatus=await getGitStatus(repoPath),resumePrompt=[`RESUME CONTEXT: You were working on wish "${slug}", group "${groupName}".`,`Status: ${group.status}. Started at: ${group.startedAt??"unknown"}.`,`Wish file: .genie/wishes/${slug}/WISH.md`,"",groupSection?`Group section:
554
+ `).count===0)throw Error(`Team "${teamName}" not found.`)}var init_team_manager=__esm(()=>{init_agent_registry();init_audit();init_builtin_agents();init_claude_native_teams();init_db();init_executor_registry();init_genie_config2();init_tmux()});var exports_protocol_router_spawn={};__export(exports_protocol_router_spawn,{spawnWorkerFromTemplate:()=>spawnWorkerFromTemplate,injectResumeContext:()=>injectResumeContext});import{exec as exec2}from"child_process";import{readFile as readFile4}from"fs/promises";import{join as join20}from"path";import{promisify as promisify2}from"util";async function resolveParentSession(_repoPath,team){let teamConfig=await getTeam2(team);if(teamConfig?.nativeTeamParentSessionId)return teamConfig.nativeTeamParentSessionId;return await discoverClaudeParentSessionId()??`genie-${team}`}function buildSpawnParams(template,parentSessionId,spawnColor,resumeSessionId){let isClaude=template.provider==="claude",sessionName=template.role?`${template.team}-${template.role}`:void 0,newSessionId=isClaude&&!resumeSessionId?crypto.randomUUID():void 0,params={provider:template.provider,team:template.team,role:template.role,skill:template.skill,extraArgs:template.extraArgs,sessionId:newSessionId,resume:isClaude?resumeSessionId:void 0,name:sessionName};if(isClaude)params.nativeTeam={enabled:!0,parentSessionId,color:spawnColor,agentType:template.role??"general-purpose",agentName:template.role};return params}function buildFullCommand(launch){if(launch.env&&Object.keys(launch.env).length>0)return`env ${Object.entries(launch.env).map(([k,v])=>`${k}=${v}`).join(" ")} ${launch.command}`;return launch.command}async function generateWorkerId(team,role){let base=role?`${team}-${role}`:team;return(await list()).some((w)=>w.id===base)?`${base}-${crypto.randomUUID().slice(0,8)}`:base}async function createExecutorForAutoSpawn(template,paneId,session,repoPath,effectiveSessionId,spawnColor,teamWindow){let agentName=template.role??"worker",agentIdentity=await findOrCreateAgent(agentName,template.team,template.role),currentExec=await getCurrentExecutor(agentIdentity.id);if(currentExec&&currentExec.state!=="terminated"&&currentExec.state!=="done"){let providerImpl=getProvider(currentExec.provider);if(providerImpl)try{await providerImpl.terminate(currentExec)}catch{}await terminateActiveExecutor(agentIdentity.id)}let pid=null;try{let{stdout:pidOut}=await execAsync(genieTmuxCmd(`display -t '${paneId}' -p '#{pane_pid}'`)),parsed=Number.parseInt(pidOut.trim(),10);if(parsed>0)pid=parsed}catch{}let executorTransport=template.provider==="codex"?"api":"tmux",executor=await createExecutor(agentIdentity.id,template.provider,executorTransport,{pid,tmuxSession:session,tmuxPaneId:paneId,tmuxWindow:teamWindow?.windowName??null,tmuxWindowId:teamWindow?.windowId??null,claudeSessionId:effectiveSessionId??null,state:"spawning",repoPath,paneColor:spawnColor??null});await setCurrentExecutor(agentIdentity.id,executor.id)}async function spawnPaneInSession(session,team,repoPath,fullCommand){let teamWindow=null;try{teamWindow=await ensureTeamWindow(session,team,repoPath)}catch{}let splitTarget=teamWindow?`-t '${teamWindow.windowId}'`:"",escapedCmd=fullCommand.replace(/'/g,"'\\''"),{stdout}=await execAsync(genieTmuxCmd(`split-window -d ${splitTarget} -P -F '#{pane_id}' '${escapedCmd}'`)),paneId=stdout.trim(),layoutTarget=`${session}:${teamWindow?.windowName??""}`;if(!teamWindow){let wins=await listWindows(session);layoutTarget=wins[0]?wins[0].id:`${session}:`}try{await execAsync(genieTmuxCmd(buildLayoutCommand(layoutTarget,resolveLayoutMode())))}catch{}return{paneId,teamWindow}}async function spawnWorkerFromTemplate(template,resumeSessionId){let repoPath=template.cwd??process.cwd(),team=template.team,parentSessionId=await resolveParentSession(repoPath,team);await ensureNativeTeam(team,`Genie team: ${team}`,parentSessionId);let spawnColor=await assignColor(team),params=buildSpawnParams(template,parentSessionId,spawnColor,resumeSessionId),launch=buildLaunchCommand(validateSpawnParams(params)),fullCommand=buildFullCommand(launch),workerId=await generateWorkerId(team,template.role),session=(await getTeam2(team))?.tmuxSessionName??await resolveRepoSession(repoPath)??await getCurrentSessionName()??team,{paneId,teamWindow}=await spawnPaneInSession(session,team,repoPath,fullCommand),now=new Date().toISOString(),agentName=template.role??"worker",isClaude=template.provider==="claude",effectiveSessionId=resumeSessionId??params.sessionId,workerEntry={id:workerId,paneId,session,provider:template.provider,transport:"tmux",role:template.role,skill:template.skill,team,worktree:null,startedAt:now,state:"spawning",lastStateChange:now,repoPath,claudeSessionId:effectiveSessionId,nativeTeamEnabled:isClaude,nativeAgentId:`${agentName}@${team}`,nativeColor:spawnColor,parentSessionId,window:teamWindow?.windowName,windowName:teamWindow?.windowName,windowId:teamWindow?.windowId};await register(workerEntry);try{await createExecutorForAutoSpawn(template,paneId,session,repoPath,effectiveSessionId,spawnColor,teamWindow)}catch{}if(isClaude)await registerNativeMember(team,{agentName,agentType:template.role??"general-purpose",color:spawnColor??"blue",tmuxPaneId:paneId,cwd:repoPath}),await writeNativeInbox(team,"team-lead",{from:agentName,text:`Worker ${agentName} (${template.provider}) auto-spawned${resumeSessionId?" with --resume":""}. Ready for tasks.`,summary:`${agentName} auto-spawned`,timestamp:now,color:spawnColor??"blue",read:!1});if(spawnColor)await applyPaneColor(paneId,spawnColor,teamWindow?.windowId);return await injectResumeContext(repoPath,workerId,agentName,team),{worker:workerEntry,paneId,workerId}}function extractGroupSection(content,groupName){let escaped=groupName.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),pattern=new RegExp(`^### Group ${escaped}:`,"m"),match=content.match(pattern);if(!match||match.index===void 0)return null;let start=match.index,nextBoundary=content.slice(start).slice(1).search(/^### Group \d|^---$/m),end=nextBoundary!==-1?start+1+nextBoundary:content.length;return content.slice(start,end).trim()}async function getRecentGitLog(repoPath,count=3){try{let{stdout}=await execAsync(`git -C '${repoPath}' log --oneline -${count} 2>/dev/null`);return stdout.trim()}catch{return""}}async function getGitStatus(repoPath){try{let{stdout}=await execAsync(`git -C '${repoPath}' status --short 2>/dev/null`);return stdout.trim()}catch{return""}}async function injectResumeContext(repoPath,workerId,agentName,_team){try{let match=await findAnyGroupByAssignee(workerId,repoPath)??await findAnyGroupByAssignee(agentName,repoPath);if(!match)return;let{slug,groupName,group}=match,wishPath=join20(repoPath,".genie","wishes",slug,"WISH.md"),groupSection="";try{let wishContent=await readFile4(wishPath,"utf-8");groupSection=extractGroupSection(wishContent,groupName)??""}catch{}let gitLog=await getRecentGitLog(repoPath),gitStatus=await getGitStatus(repoPath),resumePrompt=[`RESUME CONTEXT: You were working on wish "${slug}", group "${groupName}".`,`Status: ${group.status}. Started at: ${group.startedAt??"unknown"}.`,`Wish file: .genie/wishes/${slug}/WISH.md`,"",groupSection?`Group section:
555
555
  ${groupSection}`:"","",gitLog?`Last git log:
556
556
  ${gitLog}`:"","",gitStatus?`Uncommitted changes:
557
557
  ${gitStatus}`:"","","Pick up where you left off. Read the wish file for full context."].filter(Boolean).join(`
@@ -831,7 +831,7 @@ process.on('SIGTERM', () => { server.close(); process.exit(0); });
831
831
  process.on('SIGINT', () => { server.close(); process.exit(0); });
832
832
  `,{mode:420});let{spawn:spawnChild}=__require("child_process");spawnChild("node",[scriptFile],{detached:!0,stdio:"ignore"}).unref();for(let i2=0;i2<30;i2++)if(await new Promise((r)=>setTimeout(r,100)),isRelayAlive(pidFile))return!0;return!1}catch{return!1}}async function generateWorkerId2(team,role){let base=role?`${team}-${role}`:team;if(!(await list()).some((w)=>w.id===base))return base;let suffix=crypto.randomUUID().slice(0,8);return`${base}-${suffix}`}async function capturePanePid(paneId){if(paneId==="inline")return null;try{let{execSync:execSync4}=__require("child_process"),output=execSync4(genieTmuxCmd(`display -t '${paneId}' -p '#{pane_pid}'`),{encoding:"utf-8"}).trim(),pid=Number.parseInt(output,10);return pid>0?pid:null}catch{return null}}function resolveExecutorTransport(provider,spawnTransport){if(provider==="codex")return"api";return spawnTransport==="inline"?"process":"tmux"}async function terminateActiveExecutorWithCleanup(agentIdentityId){try{let currentExec=await getCurrentExecutor(agentIdentityId);if(!currentExec||currentExec.state==="terminated"||currentExec.state==="done")return;let provider=getProvider(currentExec.provider);if(provider)try{await provider.terminate(currentExec)}catch{}await terminateActiveExecutor(agentIdentityId)}catch{}}async function createAndLinkExecutor(agentIdentityId,provider,transport,opts){try{let executor=await createExecutor(agentIdentityId,provider,transport,opts);return await setCurrentExecutor(agentIdentityId,executor.id),executor.id}catch{return null}}async function registerSpawnWorker(ctx,paneId,windowInfo){let nt=ctx.validated.nativeTeam,workerEntry={id:ctx.workerId,paneId,session:ctx.validated.team,provider:ctx.validated.provider,transport:ctx.transport,role:ctx.validated.role,skill:ctx.validated.skill,team:ctx.validated.team,worktree:null,startedAt:ctx.now,state:"spawning",lastStateChange:ctx.now,repoPath:ctx.cwd,claudeSessionId:ctx.claudeSessionId,nativeTeamEnabled:nt?.enabled??!1,nativeAgentId:`${ctx.agentName}@${ctx.validated.team}`,nativeColor:nt?.color??ctx.spawnColor,parentSessionId:nt?.parentSessionId??ctx.parentSessionId,window:windowInfo?.windowName,windowName:windowInfo?.windowName,windowId:windowInfo?.windowId,autoResume:ctx.autoResume===!1?!1:void 0,resumeAttempts:0};await register(workerEntry);let role=ctx.validated.role??ctx.agentName;if(role!=="council")try{await hireAgent(ctx.validated.team,role)}catch{}return workerEntry}async function notifySpawnJoin(ctx,paneId){let nt=ctx.validated.nativeTeam;if(!nt?.enabled)return;await registerNativeMember(ctx.validated.team,{agentName:ctx.agentName,agentType:nt.agentType??ctx.validated.role??"general-purpose",color:nt.color??ctx.spawnColor??"blue",tmuxPaneId:paneId,cwd:ctx.cwd,planModeRequired:nt.planModeRequired}),await writeNativeInbox(ctx.validated.team,"team-lead",{from:ctx.agentName,text:`Worker ${ctx.agentName} (${ctx.validated.provider}) joined team ${ctx.validated.team}. cwd: ${ctx.cwd}. Ready for tasks.`,summary:`${ctx.agentName} (${ctx.validated.provider}) joined`,timestamp:new Date().toISOString(),color:nt.color??ctx.spawnColor??"blue",read:!1})}function registerOtelRelayPane(workerId,paneId,agentName,spawnColor,repoPath){let{writeFileSync:wfs}=__require("fs"),{join:pjoin}=__require("path"),{homedir:hdir}=__require("os"),rd=pjoin(hdir(),".genie","relay");wfs(pjoin(rd,`${workerId}-pane`),paneId),wfs(pjoin(rd,`${workerId}-meta`),JSON.stringify({agent:agentName,color:spawnColor,repoPath}))}function printSpawnInfo(ctx,paneId,workerEntry){let nt=ctx.validated.nativeTeam;if(console.log(`Agent "${ctx.workerId}" spawned.`),console.log(` Provider: ${ctx.launch.provider}`),console.log(` Command: ${ctx.fullCommand}`),console.log(` Team: ${ctx.validated.team}`),console.log(` Pane: ${paneId}`),ctx.validated.role)console.log(` Role: ${ctx.validated.role}`);if(ctx.validated.skill)console.log(` Skill: ${ctx.validated.skill}`);if(workerEntry.claudeSessionId)console.log(` Session: ${workerEntry.claudeSessionId}`);if(console.log(` Layout: ${ctx.layoutMode}`),nt?.enabled)console.log(" Native: enabled"),console.log(` AgentID: ${workerEntry.nativeAgentId}`),console.log(` Color: ${nt.color}`);if(ctx.otelRelayActive)console.log(` OTel: relay on port ${OTEL_RELAY_PORT}`)}function shellQuote2(arg){return`'${arg.replace(/'/g,"'\\''")}'`}function writeTmuxLaunchScript(workerId,fullCommand){let{chmodSync:chmodSync2,mkdirSync:mkdirSync7,writeFileSync:writeFileSync6}=__require("fs"),{join:join22}=__require("path"),{homedir:homedir16}=__require("os"),dir=join22(homedir16(),".genie","spawn-scripts");mkdirSync7(dir,{recursive:!0});let safeId=workerId.replace(/[^a-zA-Z0-9._-]/g,"-"),scriptPath=join22(dir,`${safeId}-${Date.now().toString(36)}.sh`);return writeFileSync6(scriptPath,`#!/bin/sh
833
833
  exec ${fullCommand}
834
- `,{mode:448}),chmodSync2(scriptPath,448),scriptPath}function buildInitialSplitWindowCommand(windowId,cwd,fullCommand){let cwdFlag=cwd?` -c ${shellQuote2(cwd)}`:"";return genieTmuxCmd(`split-window -d -t ${shellQuote2(windowId)}${cwdFlag} -P -F '#{pane_id}' ${shellQuote2(fullCommand)}`)}async function resolveSpawnTeamWindow(team,cwd,sessionOverride){if(!team)return null;try{let sessionName=sessionOverride??await getCurrentSessionName(team);if(!sessionName)sessionName=(await getTeam2(team))?.tmuxSessionName??team;return await ensureTeamWindow(sessionName,team,cwd)}catch(err){return console.warn(`Warning: could not ensure team window for "${team}": ${err instanceof Error?err.message:err}`),null}}async function autoConfirmTrustPrompt(paneId){let{execSync:execSync4}=__require("child_process"),maxWaitMs=15000,pollMs=500,start=Date.now();while(Date.now()-start<15000){await new Promise((r)=>setTimeout(r,500));let content;try{content=execSync4(genieTmuxCmd(`capture-pane -t '${paneId}' -p`),{encoding:"utf-8"})}catch{return}if(content.includes("trust this folder")||content.includes("Quick safety check")){try{execSync4(genieTmuxCmd(`send-keys -t '${paneId}' Enter`),{encoding:"utf-8"})}catch{}return}if(content.includes("Claude Code")||content.includes("\u276F")||content.includes("Churning"))return}}function createTmuxPane(ctx,teamWindow){let{execSync:execSync4}=__require("child_process"),useLaunchScript=ctx.validated.provider==="claude"&&Boolean(ctx.validated.nativeTeam?.enabled),tmuxCommand=useLaunchScript?shellQuote2(writeTmuxLaunchScript(ctx.workerId,ctx.fullCommand)):shellQuote2(ctx.fullCommand),tmuxPrefix=genieTmuxCmd("");if(teamWindow?.created){let cwdFlag2=ctx.cwd?` -c ${shellQuote2(ctx.cwd)}`:"",paneId=execSync4(`${tmuxPrefix}split-window -d -t ${shellQuote2(teamWindow.windowId)}${cwdFlag2} -P -F '#{pane_id}' ${tmuxCommand}`,{encoding:"utf-8"}).trim();try{execSync4(genieTmuxCmd(`kill-pane -t '${teamWindow.paneId}'`),{stdio:"ignore"})}catch{}return paneId}let splitTarget=teamWindow?`-t '${teamWindow.windowId}'`:"",cwdFlag=ctx.cwd?`-c '${ctx.cwd}'`:"";if(useLaunchScript){let splitCmd2=`${tmuxPrefix}split-window -d ${splitTarget} ${cwdFlag} -P -F '#{pane_id}' ${tmuxCommand}`;return execSync4(splitCmd2,{encoding:"utf-8"}).trim()}let escapedCmd=ctx.fullCommand.replace(/'/g,"'\\''"),splitCmd=`${tmuxPrefix}split-window -d ${splitTarget} ${cwdFlag} -P -F '#{pane_id}' '${escapedCmd}'`;return execSync4(splitCmd,{encoding:"utf-8"}).trim()}async function applySpawnLayout(ctx,teamWindow){let{execSync:execSync4}=__require("child_process"),session=await getCurrentSessionName()??ctx.validated.team,layoutTarget=`${session}:${teamWindow?.windowName??""}`;if(!teamWindow){let wins=await listWindows(session);layoutTarget=wins[0]?wins[0].id:`${session}:`}try{execSync4(genieTmuxCmd(buildLayoutCommand(layoutTarget,ctx.layoutMode)),{stdio:"ignore"})}catch{}}async function createTmuxExecutor(ctx,paneId,pid,teamWindow){if(!ctx.agentIdentityId||!ctx.executorId)return;await createAndLinkExecutor(ctx.agentIdentityId,ctx.validated.provider,resolveExecutorTransport(ctx.validated.provider,"tmux"),{id:ctx.executorId,pid,tmuxSession:ctx.validated.team,tmuxPaneId:paneId,tmuxWindow:teamWindow?.windowName??null,tmuxWindowId:teamWindow?.windowId??null,claudeSessionId:ctx.claudeSessionId??null,state:"spawning",repoPath:ctx.cwd,paneColor:ctx.spawnColor})}async function finalizeTmuxSpawn(ctx,paneId,teamWindow,workerEntry){if(ctx.spawnColor&&paneId!=="inline")await applyPaneColor(paneId,ctx.spawnColor,teamWindow?.windowId);if(await saveTemplate({id:ctx.validated.role??ctx.workerId,provider:ctx.validated.provider,team:ctx.validated.team,role:ctx.validated.role,skill:ctx.validated.skill,cwd:ctx.cwd,extraArgs:ctx.extraArgs,nativeTeamEnabled:workerEntry.nativeTeamEnabled,lastSpawnedAt:new Date().toISOString()}),ctx.otelRelayActive&&paneId!=="%0")registerOtelRelayPane(ctx.workerId,paneId,ctx.agentName,ctx.spawnColor,ctx.cwd);if(teamWindow)console.log(` Window: ${teamWindow.windowName} (${teamWindow.windowId})`);printSpawnInfo(ctx,paneId,workerEntry)}async function awaitAgentReadiness(paneId){if(paneId==="inline")return;let result=await waitForAgentReady(paneId);if(result.ready)console.log(` \u2713 Agent ready (${(result.elapsedMs/1000).toFixed(1)}s)`);else console.log(` \u26A0 Agent readiness timeout (${Math.round(result.elapsedMs/1000)}s) \u2014 proceeding anyway`)}async function launchTmuxSpawn(ctx){let teamWindow=ctx.spawnIntoCurrentWindow?null:await resolveSpawnTeamWindow(ctx.validated.team,ctx.cwd,ctx.sessionOverride),paneId;try{paneId=createTmuxPane(ctx,teamWindow)}catch(err){return console.error(`Failed to create tmux pane: ${err instanceof Error?err.message:"unknown error"}`),process.exit(1)}let pid=await capturePanePid(paneId);if(await createTmuxExecutor(ctx,paneId,pid,teamWindow),await applySpawnLayout(ctx,teamWindow),ctx.validated.provider==="claude")await autoConfirmTrustPrompt(paneId);let workerEntry=await registerSpawnWorker(ctx,paneId,teamWindow);return await notifySpawnJoin(ctx,paneId),await finalizeTmuxSpawn(ctx,paneId,teamWindow,workerEntry),await awaitAgentReadiness(paneId),paneId}async function launchInlineSpawn(ctx){let nt=ctx.validated.nativeTeam,paneId="inline";if(ctx.agentIdentityId&&ctx.executorId)await createAndLinkExecutor(ctx.agentIdentityId,ctx.validated.provider,resolveExecutorTransport(ctx.validated.provider,"inline"),{id:ctx.executorId,claudeSessionId:ctx.claudeSessionId??null,state:"spawning",repoPath:ctx.cwd});let workerEntry=await registerSpawnWorker(ctx,"inline");if(await notifySpawnJoin(ctx,"inline"),console.log(`Agent "${ctx.workerId}" starting inline...`),console.log(` Provider: ${ctx.launch.provider} | Team: ${ctx.validated.team} | Role: ${ctx.validated.role??"-"}`),nt?.enabled)console.log(` Native: enabled | AgentID: ${workerEntry.nativeAgentId}`);console.log("");let{spawnSync}=__require("child_process"),envVars={...process.env,...ctx.launch.env??{}},result=spawnSync("sh",["-c",ctx.launch.command],{env:envVars,stdio:"inherit"});if(ctx.agentIdentityId&&ctx.executorId)await updateExecutorState(ctx.executorId,"done").catch(()=>{});if(await unregister(ctx.workerId),nt?.enabled&&ctx.agentName)await clearNativeInbox(ctx.validated.team,ctx.agentName).catch(()=>{}),await unregisterNativeMember(ctx.validated.team,ctx.agentName).catch(()=>{});return console.log(`
834
+ `,{mode:448}),chmodSync2(scriptPath,448),scriptPath}function buildInitialSplitWindowCommand(windowId,cwd,fullCommand){let cwdFlag=cwd?` -c ${shellQuote2(cwd)}`:"";return genieTmuxCmd(`split-window -d -t ${shellQuote2(windowId)}${cwdFlag} -P -F '#{pane_id}' ${shellQuote2(fullCommand)}`)}async function resolveSpawnTeamWindow(team,cwd,sessionOverride){if(!team)return null;try{let sessionName=sessionOverride;if(!sessionName)sessionName=(await getTeam2(team))?.tmuxSessionName;if(!sessionName)sessionName=await resolveRepoSession(cwd);if(!sessionName)sessionName=team;return await ensureTeamWindow(sessionName,team,cwd)}catch(err){return console.warn(`Warning: could not ensure team window for "${team}": ${err instanceof Error?err.message:err}`),null}}async function autoConfirmTrustPrompt(paneId){let{execSync:execSync4}=__require("child_process"),maxWaitMs=15000,pollMs=500,start=Date.now();while(Date.now()-start<15000){await new Promise((r)=>setTimeout(r,500));let content;try{content=execSync4(genieTmuxCmd(`capture-pane -t '${paneId}' -p`),{encoding:"utf-8"})}catch{return}if(content.includes("trust this folder")||content.includes("Quick safety check")){try{execSync4(genieTmuxCmd(`send-keys -t '${paneId}' Enter`),{encoding:"utf-8"})}catch{}return}if(content.includes("Claude Code")||content.includes("\u276F")||content.includes("Churning"))return}}function createTmuxPane(ctx,teamWindow){let{execSync:execSync4}=__require("child_process"),useLaunchScript=ctx.validated.provider==="claude"&&Boolean(ctx.validated.nativeTeam?.enabled),tmuxCommand=useLaunchScript?shellQuote2(writeTmuxLaunchScript(ctx.workerId,ctx.fullCommand)):shellQuote2(ctx.fullCommand),tmuxPrefix=genieTmuxCmd("");if(teamWindow?.created){let cwdFlag2=ctx.cwd?` -c ${shellQuote2(ctx.cwd)}`:"",paneId=execSync4(`${tmuxPrefix}split-window -d -t ${shellQuote2(teamWindow.windowId)}${cwdFlag2} -P -F '#{pane_id}' ${tmuxCommand}`,{encoding:"utf-8"}).trim();try{execSync4(genieTmuxCmd(`kill-pane -t '${teamWindow.paneId}'`),{stdio:"ignore"})}catch{}return paneId}let splitTarget=teamWindow?`-t '${teamWindow.windowId}'`:"",cwdFlag=ctx.cwd?`-c '${ctx.cwd}'`:"";if(useLaunchScript){let splitCmd2=`${tmuxPrefix}split-window -d ${splitTarget} ${cwdFlag} -P -F '#{pane_id}' ${tmuxCommand}`;return execSync4(splitCmd2,{encoding:"utf-8"}).trim()}let escapedCmd=ctx.fullCommand.replace(/'/g,"'\\''"),splitCmd=`${tmuxPrefix}split-window -d ${splitTarget} ${cwdFlag} -P -F '#{pane_id}' '${escapedCmd}'`;return execSync4(splitCmd,{encoding:"utf-8"}).trim()}async function applySpawnLayout(ctx,teamWindow){let{execSync:execSync4}=__require("child_process"),session=await getCurrentSessionName()??ctx.validated.team,layoutTarget=`${session}:${teamWindow?.windowName??""}`;if(!teamWindow){let wins=await listWindows(session);layoutTarget=wins[0]?wins[0].id:`${session}:`}try{execSync4(genieTmuxCmd(buildLayoutCommand(layoutTarget,ctx.layoutMode)),{stdio:"ignore"})}catch{}}async function createTmuxExecutor(ctx,paneId,pid,teamWindow){if(!ctx.agentIdentityId||!ctx.executorId)return;await createAndLinkExecutor(ctx.agentIdentityId,ctx.validated.provider,resolveExecutorTransport(ctx.validated.provider,"tmux"),{id:ctx.executorId,pid,tmuxSession:ctx.validated.team,tmuxPaneId:paneId,tmuxWindow:teamWindow?.windowName??null,tmuxWindowId:teamWindow?.windowId??null,claudeSessionId:ctx.claudeSessionId??null,state:"spawning",repoPath:ctx.cwd,paneColor:ctx.spawnColor})}async function finalizeTmuxSpawn(ctx,paneId,teamWindow,workerEntry){if(ctx.spawnColor&&paneId!=="inline")await applyPaneColor(paneId,ctx.spawnColor,teamWindow?.windowId);if(await saveTemplate({id:ctx.validated.role??ctx.workerId,provider:ctx.validated.provider,team:ctx.validated.team,role:ctx.validated.role,skill:ctx.validated.skill,cwd:ctx.cwd,extraArgs:ctx.extraArgs,nativeTeamEnabled:workerEntry.nativeTeamEnabled,lastSpawnedAt:new Date().toISOString()}),ctx.otelRelayActive&&paneId!=="%0")registerOtelRelayPane(ctx.workerId,paneId,ctx.agentName,ctx.spawnColor,ctx.cwd);if(teamWindow)console.log(` Window: ${teamWindow.windowName} (${teamWindow.windowId})`);printSpawnInfo(ctx,paneId,workerEntry)}async function awaitAgentReadiness(paneId){if(paneId==="inline")return;let result=await waitForAgentReady(paneId);if(result.ready)console.log(` \u2713 Agent ready (${(result.elapsedMs/1000).toFixed(1)}s)`);else console.log(` \u26A0 Agent readiness timeout (${Math.round(result.elapsedMs/1000)}s) \u2014 proceeding anyway`)}async function launchTmuxSpawn(ctx){let teamWindow=ctx.spawnIntoCurrentWindow?null:await resolveSpawnTeamWindow(ctx.validated.team,ctx.cwd,ctx.sessionOverride),paneId;try{paneId=createTmuxPane(ctx,teamWindow)}catch(err){return console.error(`Failed to create tmux pane: ${err instanceof Error?err.message:"unknown error"}`),process.exit(1)}let pid=await capturePanePid(paneId);if(await createTmuxExecutor(ctx,paneId,pid,teamWindow),await applySpawnLayout(ctx,teamWindow),ctx.validated.provider==="claude")await autoConfirmTrustPrompt(paneId);let workerEntry=await registerSpawnWorker(ctx,paneId,teamWindow);return await notifySpawnJoin(ctx,paneId),await finalizeTmuxSpawn(ctx,paneId,teamWindow,workerEntry),await awaitAgentReadiness(paneId),paneId}async function launchInlineSpawn(ctx){let nt=ctx.validated.nativeTeam,paneId="inline";if(ctx.agentIdentityId&&ctx.executorId)await createAndLinkExecutor(ctx.agentIdentityId,ctx.validated.provider,resolveExecutorTransport(ctx.validated.provider,"inline"),{id:ctx.executorId,claudeSessionId:ctx.claudeSessionId??null,state:"spawning",repoPath:ctx.cwd});let workerEntry=await registerSpawnWorker(ctx,"inline");if(await notifySpawnJoin(ctx,"inline"),console.log(`Agent "${ctx.workerId}" starting inline...`),console.log(` Provider: ${ctx.launch.provider} | Team: ${ctx.validated.team} | Role: ${ctx.validated.role??"-"}`),nt?.enabled)console.log(` Native: enabled | AgentID: ${workerEntry.nativeAgentId}`);console.log("");let{spawnSync}=__require("child_process"),envVars={...process.env,...ctx.launch.env??{}},result=spawnSync("sh",["-c",ctx.launch.command],{env:envVars,stdio:"inherit"});if(ctx.agentIdentityId&&ctx.executorId)await updateExecutorState(ctx.executorId,"done").catch(()=>{});if(await unregister(ctx.workerId),nt?.enabled&&ctx.agentName)await clearNativeInbox(ctx.validated.team,ctx.agentName).catch(()=>{}),await unregisterNativeMember(ctx.validated.team,ctx.agentName).catch(()=>{});return console.log(`
835
835
  Agent "${ctx.workerId}" session ended.`),process.exit(result.status??0)}function prependEnvVars(command,env){if(!env||Object.keys(env).length===0)return command;return`env ${Object.entries(env).map(([k,v])=>`${k}=${v}`).join(" ")} ${command}`}async function rejectDuplicateRole(team,role){let existing=await list();for(let w of existing)if(w.role===role&&w.team===team){if(await isPaneAlive(w.paneId))console.error(`Error: Worker with role "${role}" already exists in team "${team}" (state: ${w.state}, pane: ${w.paneId})
836
836
  Use a different --role name for a second worker, e.g.: --role ${role}-2`),process.exit(1);await unregister(w.id)}}async function resolveNativeTeam(team,_repoPath,options){let parentSessionId=(await getTeam2(team))?.nativeTeamParentSessionId;if(!parentSessionId)parentSessionId=await discoverClaudeParentSessionId()??`genie-${team}`;await ensureNativeTeam(team,`Genie team: ${team}`,parentSessionId);let spawnColor=options.color??await assignColor(team),nativeTeam;if(options.provider==="claude")nativeTeam={enabled:!0,parentSessionId,color:spawnColor,agentType:options.role??"general-purpose",planModeRequired:options.planMode,permissionMode:options.permissionMode,agentName:options.role};return{parentSessionId,spawnColor,nativeTeam}}async function resolveAgentForSpawn(name,options){let resolved=await resolve3(name);if(!resolved)console.error(`Error: Agent "${name}" not found in directory or built-ins.`),console.error(` Register with: genie dir add ${name} --dir <path>`),console.error(" Or use a built-in: engineer, reviewer, qa, fix, ..."),process.exit(1);let entry=resolved.entry,identityPath=null;if(resolved.builtin)identityPath=resolveBuiltinAgentPath(name);else if(entry.dir)identityPath=loadIdentity(entry);return{entry,repoPath:options.cwd??(entry.repo||void 0)??(entry.dir||void 0)??process.cwd(),identityPath,model:options.model??entry.model}}async function buildSpawnParams2(name,team,options,agent){let params={provider:options.provider,team,role:name,skill:options.skill,extraArgs:options.extraArgs,model:agent.model,systemPromptFile:agent.identityPath??void 0,promptMode:agent.entry.promptMode,initialPrompt:options.initialPrompt},{parentSessionId,spawnColor,nativeTeam}=await resolveNativeTeam(team,agent.repoPath,{...options,role:name});if(nativeTeam)params.nativeTeam=nativeTeam;try{let{injectTeamHooks:injectTeamHooks2}=await Promise.resolve().then(() => (init_inject(),exports_inject));if(await injectTeamHooks2(team))console.log(` Hooks: injected genie hook dispatch into team "${team}"`)}catch(err){console.warn(`Warning: could not inject hooks for team "${team}": ${err instanceof Error?err.message:err}`)}if(params.provider==="claude")params.sessionId=crypto.randomUUID();if(params.provider==="claude"){if(await startOtelReceiver())params.otelPort=getOtelPort(),params.otelLogPrompts=!0}return{params,parentSessionId,spawnColor}}async function handleWorkerSpawn(name,options){let effectiveRole=options.role??name,agent=await resolveAgentForSpawn(name,options),teamWasExplicit=Boolean(options.team),team=options.team||await discoverTeamName();if(!team)return console.error("Error: --team is required (or set GENIE_TEAM, or run inside a genie session)"),process.exit(1);await rejectDuplicateRole(team,effectiveRole);let teamConfig=await getTeam2(team);if(teamConfig?.worktreePath)agent={...agent,repoPath:teamConfig.worktreePath};let{params,parentSessionId,spawnColor}=await buildSpawnParams2(effectiveRole,team,options,agent);if(!params.name)params.name=`${params.team}-${effectiveRole}`;let validated=validateSpawnParams(params),launch=buildLaunchCommand(validated),layoutMode=resolveLayoutMode(options.layout),workerId=await generateWorkerId2(validated.team,effectiveRole),insideTmux=Boolean(process.env.TMUX||options.session),nt=validated.nativeTeam,now=new Date().toISOString(),agentName=nt?.agentName??effectiveRole,agentIdentity=await findOrCreateAgent(agentName,team,effectiveRole);await terminateActiveExecutorWithCleanup(agentIdentity.id);let executorId=crypto.randomUUID(),otelRelayActive=!1;if(!nt?.enabled&&validated.provider==="codex"&&insideTmux)ensureCodexOtelConfig(),otelRelayActive=await ensureOtelRelay(validated.team);let fullCommand=prependEnvVars(launch.command,launch.env),ctx={workerId,validated,launch,layoutMode,fullCommand,agentName,spawnColor,parentSessionId,claudeSessionId:validated.sessionId,otelRelayActive,now,transport:insideTmux?"tmux":"inline",extraArgs:options.extraArgs,cwd:agent.repoPath,spawnIntoCurrentWindow:!teamWasExplicit&&insideTmux&&!options.session,sessionOverride:options.session,autoResume:options.autoResume,agentIdentityId:agentIdentity.id,executorId};if(recordAuditEvent("worker",workerId,"spawn",getActor(),{name,team:validated.team,provider:validated.provider}).catch(()=>{}),insideTmux)return await launchTmuxSpawn(ctx);return await launchInlineSpawn(ctx)}async function cleanupWorkerNativeTeam(w){if(!w.team||!w.nativeAgentId)return;let agentName=w.nativeAgentId.split("@")[0];await clearNativeInbox(w.team,agentName).catch(()=>{}),await unregisterNativeMember(w.team,agentName).catch(()=>{})}function killWorkerPane(w){try{let{execSync:execSync4}=__require("child_process"),currentPane=execSync4(genieTmuxCmd("display-message -p '#{pane_id}'"),{encoding:"utf-8"}).trim();if(w.paneId&&/^(%\d+|inline)$/.test(w.paneId)&&w.paneId!==currentPane)execSync4(genieTmuxCmd(`kill-pane -t ${w.paneId}`),{stdio:"ignore"});else if(w.paneId===currentPane)console.log(" (skipped pane kill \u2014 would kill current session)")}catch{}}function cleanupRelayFiles(id){try{let{join:join22}=__require("path"),{homedir:homedir16}=__require("os"),{unlinkSync:unlinkSync5}=__require("fs"),relayDir=join22(homedir16(),".genie","relay");for(let suffix of["-pane","-meta"])try{unlinkSync5(join22(relayDir,`${id}${suffix}`))}catch{}}catch{}}async function resolveWorkerByName(name){let exact=await get(name);if(exact)return exact;let workers=await list(),byRole=workers.filter((w)=>w.role===name);if(byRole.length===1)return byRole[0];if(byRole.length>1){console.error(`Multiple agents with role "${name}". Specify full ID:`);for(let w of byRole)console.error(` ${w.id} (team: ${w.team})`);process.exit(1)}let bySuffix=workers.filter((w)=>w.id.endsWith(`-${name}`));if(bySuffix.length===1)return bySuffix[0];if(bySuffix.length>1){console.error(`Multiple agents matching "${name}". Specify full ID:`);for(let w of bySuffix)console.error(` ${w.id}`);process.exit(1)}console.error(`Agent "${name}" not found.`),console.error(" Run `genie agent list` to see agents."),process.exit(1)}async function handleWorkerKill(name){let w=await resolveWorkerByName(name);killWorkerPane(w),cleanupRelayFiles(w.id),await cleanupWorkerNativeTeam(w),await unregister(w.id),console.log(`Agent "${w.id}" killed and unregistered (template preserved).`),recordAuditEvent("worker",w.id,"kill",getActor(),{name}).catch(()=>{})}async function handleWorkerStop(name){let w=await resolveWorkerByName(name);if(w.state==="suspended"){console.log(`Agent "${w.id}" is already stopped.`);return}let{suspendWorker:suspendWorker2}=await Promise.resolve().then(() => (init_idle_timeout(),exports_idle_timeout));if(await suspendWorker2(w.id)){if(console.log(`Agent "${w.id}" stopped.`),w.claudeSessionId)console.log(` Session preserved: ${w.claudeSessionId}`);console.log(` Send a message to auto-resume: genie send '...' --to ${w.id}`),recordAuditEvent("worker",w.id,"stop",getActor(),{name}).catch(()=>{})}else console.error(`Failed to stop agent "${w.id}".`),process.exit(1)}async function isResumeEligible(w){if(!w.claudeSessionId)return!1;if(w.state==="done")return!1;let paneAlive=await isPaneAlive(w.paneId);if((w.state==="suspended"||w.state==="error")&&!paneAlive)return!0;if(!paneAlive&&(w.state==="working"||w.state==="idle"||w.state==="spawning"))return!0;return!1}async function resumeAllAgents(){let workers=await list(),toResume=[];for(let w of workers)if(await isResumeEligible(w))toResume.push(w);if(toResume.length===0){console.log("No eligible agents to resume.");return}console.log(`Resuming ${toResume.length} agent(s)...`);for(let w of toResume)try{await resumeAgent(w)}catch(err){console.error(` Failed to resume "${w.id}": ${err instanceof Error?err.message:err}`)}}async function handleWorkerResume(name,options){if(options.all)return resumeAllAgents();if(!name)console.error("Error: provide an agent name, or use --all to resume all eligible agents."),process.exit(1);let w=await resolveWorkerByName(name);if(!w.claudeSessionId)console.error(`Error: Agent "${w.id}" has no Claude session ID \u2014 cannot resume.`),console.error(" Only agents spawned with the Claude provider have resumable sessions."),process.exit(1);if(await isPaneAlive(w.paneId)){console.log(`Agent "${w.id}" is already running (pane ${w.paneId} is alive).`);return}await resumeAgent(w)}function buildResumeParams(agent,template){let agentName=agent.role??agent.id,provider=template?.provider??agent.provider??"claude",team=template?.team??agent.team??"genie";return{provider,team,role:agentName,skill:template?.skill??agent.skill,extraArgs:template?.extraArgs,resume:agent.claudeSessionId,name:`${team}-${agentName}`}}function formatGroupStatus(name,group,allGroups){let detail=group.status;if(group.completedAt)detail+=` (completed at ${group.completedAt})`;else if(group.startedAt)detail+=` (started at ${group.startedAt})`;if(group.status==="blocked"&&group.dependsOn.length>0){let pending=group.dependsOn.filter((dep)=>allGroups[dep]?.status!=="done");if(pending.length>0)detail+=` (depends on ${pending.join(", ")})`}return`Group ${name}: ${detail}`}async function buildResumeContext(agent){if(agent.role==="team-lead"&&agent.wishSlug)try{let state=await(await Promise.resolve().then(() => (init_wish_state(),exports_wish_state))).getState(agent.wishSlug,agent.repoPath);if(state){let groupLines=Object.entries(state.groups).map(([name,group])=>formatGroupStatus(name,group,state.groups));return["You were resumed after a crash. Here's where you left off:",`Wish: ${state.wish}`,"",...groupLines,"",`Continue from where you left off. Run \`genie status ${state.wish}\` to verify, then dispatch the next wave.`].join(`
837
837
  `)}}catch{}if(agent.team)return"You were resumed. Check your team's current state with `genie status`.";return}async function buildFullResumeParams(agent,template){let params=buildResumeParams(agent,template),resumeContext=await buildResumeContext(agent);if(resumeContext)params.initialPrompt=resumeContext;if(agent.nativeTeamEnabled){let nativeResult=await resolveNativeTeam(params.team,agent.repoPath,{provider:params.provider,role:params.role,color:agent.nativeColor});if(nativeResult.nativeTeam)params.nativeTeam=nativeResult.nativeTeam}return params}async function createResumeExecutor(agent,params,paneId,teamWindow,cwd,spawnColor){let resumeAgentName=agent.role??agent.id,resumeTeam=agent.team??params.team,agentIdentity=await findOrCreateAgent(resumeAgentName,resumeTeam,agent.role);await terminateActiveExecutorWithCleanup(agentIdentity.id);let pid=await capturePanePid(paneId);await createAndLinkExecutor(agentIdentity.id,params.provider,resolveExecutorTransport(params.provider,"tmux"),{pid,tmuxSession:params.team,tmuxPaneId:paneId,tmuxWindow:teamWindow?.windowName??null,tmuxWindowId:teamWindow?.windowId??null,claudeSessionId:agent.claudeSessionId??null,state:"spawning",repoPath:cwd,paneColor:spawnColor})}async function resumeAgent(agent){let template=(await listTemplates()).find((t)=>t.id===(agent.role??agent.id));await update(agent.id,{resumeAttempts:0});let params=await buildFullResumeParams(agent,template),validated=validateSpawnParams(params),launch=buildLaunchCommand(validated),fullCommand=prependEnvVars(launch.command,launch.env),now=new Date().toISOString();if(!process.env.TMUX)console.error("Error: resume requires tmux. Start a tmux session first."),process.exit(1);let ctx={workerId:agent.id,validated,launch,layoutMode:resolveLayoutMode(void 0),fullCommand,agentName:agent.role??agent.id,spawnColor:agent.nativeColor??"blue",parentSessionId:agent.parentSessionId??`genie-${params.team}`,claudeSessionId:agent.claudeSessionId,otelRelayActive:!1,now,transport:"tmux",extraArgs:template?.extraArgs,cwd:template?.cwd??agent.repoPath,spawnIntoCurrentWindow:!1,autoResume:agent.autoResume},teamWindow=await resolveSpawnTeamWindow(validated.team,ctx.cwd),paneId;try{paneId=createTmuxPane(ctx,teamWindow)}catch(err){console.error(`Failed to create tmux pane: ${err instanceof Error?err.message:"unknown error"}`),process.exit(1)}if(await createResumeExecutor(agent,validated,paneId,teamWindow,ctx.cwd,ctx.spawnColor),await applySpawnLayout(ctx,teamWindow),await update(agent.id,{paneId,state:"spawning",startedAt:now,lastStateChange:now,suspendedAt:void 0,windowName:teamWindow?.windowName,windowId:teamWindow?.windowId,window:teamWindow?.windowName}),await notifySpawnJoin(ctx,paneId),await injectResumeContext(ctx.cwd??agent.repoPath??process.cwd(),agent.id,agent.role??agent.id,params.team),ctx.spawnColor&&paneId!=="inline")await applyPaneColor(paneId,ctx.spawnColor,teamWindow?.windowId);if(recordAuditEvent("worker",agent.id,"resumed",getActor(),{claudeSessionId:agent.claudeSessionId,team:agent.team}).catch(()=>{}),console.log(`Agent "${agent.id}" resumed.`),console.log(` Session: ${agent.claudeSessionId}`),console.log(` Pane: ${paneId}`),teamWindow)console.log(` Window: ${teamWindow.windowName} (${teamWindow.windowId})`)}async function buildWorkerStatusMap(workers){let statusMap=new Map;for(let w of workers){let name=w.role||w.id;if(await isPaneAlive(w.paneId))statusMap.set(name,{state:w.state,team:w.team||"-"});else if(w.state==="suspended"||w.state==="error"){let attempts=w.resumeAttempts??0,max=w.maxResumeAttempts??3,autoStr=w.autoResume===!1?"off":"on";statusMap.set(name,{state:`${w.state} (${attempts}/${max} resumes, auto-resume: ${autoStr})`,team:w.team||"-",resumeAttempts:attempts,maxResumeAttempts:max,autoResume:w.autoResume!==!1})}}return statusMap}async function handleLsCommand(options){let dirEntries=await ls(),workers=await list(),statusMap=await buildWorkerStatusMap(workers),entries=[];for(let entry of dirEntries){let running=statusMap.get(entry.name);entries.push({name:entry.name,dir:entry.dir||"-",status:running?running.state:"offline",team:running?.team||"-",model:entry.model||"-",resumeAttempts:running?.resumeAttempts,maxResumeAttempts:running?.maxResumeAttempts,autoResume:running?.autoResume}),statusMap.delete(entry.name)}for(let[name,info]of statusMap)entries.push({name,dir:"(built-in)",status:info.state,team:info.team,model:"-",resumeAttempts:info.resumeAttempts,maxResumeAttempts:info.maxResumeAttempts,autoResume:info.autoResume});if(options.json){console.log(JSON.stringify(entries,null,2));return}if(entries.length===0){console.log("No agents registered. Use `genie dir add <name> --dir <path>` to register one.");return}console.log(""),console.log(formatLsRow("NAME","DIR","STATUS","TEAM","MODEL")),console.log("-".repeat(106));for(let e of entries)console.log(formatLsRow(e.name,e.dir,e.status,e.team,e.model));console.log("")}function formatLsRow(name,dir,status,team,model){return`${name.padEnd(20).substring(0,20)}${dir.padEnd(30).substring(0,30)}${status.padEnd(44).substring(0,44)}${team.padEnd(12).substring(0,12)}${model}`}var init_agents=__esm(()=>{init_agent_directory();init_agent_registry();init_audit();init_builtin_agents();init_claude_native_teams();init_codex_config();init_executor_registry();init_otel_receiver();init_protocol_router_spawn();init_provider_adapters();init_registry();init_spawn_command();init_team_manager();init_tmux_wrapper();init_tmux();init_tmux()});var exports_workspace={};__export(exports_workspace,{scanAgents:()=>scanAgents2,getWorkspaceConfig:()=>getWorkspaceConfig,findWorkspace:()=>findWorkspace});import{existsSync as existsSync19,readFileSync as readFileSync9,readdirSync as readdirSync5}from"fs";import{dirname as dirname5,join as join22,resolve as resolve4,sep}from"path";function findWorkspace(cwd){let startDir=resolve4(cwd??process.cwd()),current=startDir;while(!0){let candidate=join22(current,WORKSPACE_MARKER);if(existsSync19(candidate)){let agent=detectAgent(startDir,current);return{root:current,agent:agent??void 0}}let parent=dirname5(current);if(parent===current)break;current=parent}return null}function detectAgent(startDir,workspaceRoot){let agentsDir=join22(workspaceRoot,"agents"),relative=startDir.slice(agentsDir.length);if(!startDir.startsWith(agentsDir)||relative.length>0&&relative[0]!==sep)return null;let parts=relative.split(sep).filter(Boolean);if(parts.length===0)return null;let agentName=parts[0],agentsMd=join22(agentsDir,agentName,"AGENTS.md");if(existsSync19(agentsMd))return agentName;return null}function getWorkspaceConfig(root){let configPath2=join22(root,WORKSPACE_MARKER),raw=readFileSync9(configPath2,"utf-8");return JSON.parse(raw)}function scanAgents2(root){let agentsDir=join22(root,"agents");if(!existsSync19(agentsDir))return[];try{return readdirSync5(agentsDir,{withFileTypes:!0}).filter((d)=>d.isDirectory()&&existsSync19(join22(agentsDir,d.name,"AGENTS.md"))).map((d)=>d.name).sort()}catch{return[]}}var WORKSPACE_MARKER=".genie/workspace.json";var init_workspace=()=>{};import{existsSync as existsSync20,readFileSync as readFileSync10,renameSync as renameSync2,writeFileSync as writeFileSync6}from"fs";import{homedir as homedir16}from"os";import{join as join23}from"path";async function regenerateAgentCache(){try{if(!await isAvailable())return;let entries=(await(await getConnection())`
@@ -864,9 +864,9 @@ Use a different --role name for a second worker, e.g.: --role ${role}-2`),proces
864
864
  ${item.dependencies??[]}
865
865
  )
866
866
  RETURNING id
867
- `;if(rows.length===0)throw Error(`Failed to insert item "${item.name}" \u2014 no id returned.`);return rows[0].id}async function removeItemFromStore(name){return(await(await getConnection())`DELETE FROM app_store WHERE name = ${name}`).count>0}async function updateItemInStore(name,updates){let sql=await getConnection(),s={};if(updates.name!==void 0)s.name=updates.name;if(updates.itemType!==void 0)s.item_type=updates.itemType;if(updates.version!==void 0)s.version=updates.version;if(updates.description!==void 0)s.description=updates.description;if(updates.authorName!==void 0)s.author_name=updates.authorName;if(updates.authorUrl!==void 0)s.author_url=updates.authorUrl;if(updates.gitUrl!==void 0)s.git_url=updates.gitUrl;if(updates.installPath!==void 0)s.install_path=updates.installPath;if(updates.manifest!==void 0)s.manifest=sql.json(updates.manifest);if(updates.tags!==void 0)s.tags=updates.tags;if(updates.category!==void 0)s.category=updates.category;if(updates.license!==void 0)s.license=updates.license;if(updates.dependencies!==void 0)s.dependencies=updates.dependencies;if(Object.keys(s).length===0)return!1;return s.updated_at=sql`now()`,(await sql`UPDATE app_store SET ${sql(s)} WHERE name = ${name}`).count>0}async function getItemFromStore(name){let rows=await(await getConnection())`SELECT * FROM app_store WHERE name = ${name}`;return rows.length>0?rows[0]:null}async function listItemsFromStore(itemType){let sql=await getConnection();return itemType?await sql`SELECT * FROM app_store WHERE item_type = ${itemType} ORDER BY name`:await sql`SELECT * FROM app_store ORDER BY name`}var GENIE_HOME3,CACHE_FILE="agent-directory.json",CACHE_BACKUP="agent-directory.json.bak";var init_agent_cache=__esm(()=>{init_audit();init_db();GENIE_HOME3=process.env.GENIE_HOME??join23(homedir16(),".genie")});var exports_session_capture={};__export(exports_session_capture,{setLiveWorkPending:()=>setLiveWorkPending,liveWorkPending:()=>liveWorkPending,ingestFileFull:()=>ingestFileFull,ingestFile:()=>ingestFile,discoverAllJsonlFiles:()=>discoverAllJsonlFiles,buildWorkerMap:()=>buildWorkerMap});import{open as open2,readdir as readdir4,stat as stat3}from"fs/promises";import{homedir as homedir17}from"os";import{basename as basename2,join as join24}from"path";function setLiveWorkPending(v){liveWorkPending=v}function extractSubTool(toolName,input){let obj=input;switch(toolName){case"Bash":return(obj?.command??"").split(`
867
+ `;if(rows.length===0)throw Error(`Failed to insert item "${item.name}" \u2014 no id returned.`);return rows[0].id}async function removeItemFromStore(name){return(await(await getConnection())`DELETE FROM app_store WHERE name = ${name}`).count>0}async function updateItemInStore(name,updates){let sql=await getConnection(),s={};if(updates.name!==void 0)s.name=updates.name;if(updates.itemType!==void 0)s.item_type=updates.itemType;if(updates.version!==void 0)s.version=updates.version;if(updates.description!==void 0)s.description=updates.description;if(updates.authorName!==void 0)s.author_name=updates.authorName;if(updates.authorUrl!==void 0)s.author_url=updates.authorUrl;if(updates.gitUrl!==void 0)s.git_url=updates.gitUrl;if(updates.installPath!==void 0)s.install_path=updates.installPath;if(updates.manifest!==void 0)s.manifest=sql.json(updates.manifest);if(updates.tags!==void 0)s.tags=updates.tags;if(updates.category!==void 0)s.category=updates.category;if(updates.license!==void 0)s.license=updates.license;if(updates.dependencies!==void 0)s.dependencies=updates.dependencies;if(Object.keys(s).length===0)return!1;return s.updated_at=sql`now()`,(await sql`UPDATE app_store SET ${sql(s)} WHERE name = ${name}`).count>0}async function getItemFromStore(name){let rows=await(await getConnection())`SELECT * FROM app_store WHERE name = ${name}`;return rows.length>0?rows[0]:null}async function listItemsFromStore(itemType){let sql=await getConnection();return itemType?await sql`SELECT * FROM app_store WHERE item_type = ${itemType} ORDER BY name`:await sql`SELECT * FROM app_store ORDER BY name`}var GENIE_HOME3,CACHE_FILE="agent-directory.json",CACHE_BACKUP="agent-directory.json.bak";var init_agent_cache=__esm(()=>{init_audit();init_db();GENIE_HOME3=process.env.GENIE_HOME??join23(homedir16(),".genie")});var exports_session_capture={};__export(exports_session_capture,{setLiveWorkPending:()=>setLiveWorkPending,liveWorkPending:()=>liveWorkPending,ingestFileFull:()=>ingestFileFull,ingestFile:()=>ingestFile,discoverAllJsonlFiles:()=>discoverAllJsonlFiles,buildWorkerMap:()=>buildWorkerMap});import{open as open2,readdir as readdir4,stat as stat3}from"fs/promises";import{homedir as homedir17}from"os";import{basename as basename3,join as join24}from"path";function setLiveWorkPending(v){liveWorkPending=v}function extractSubTool(toolName,input){let obj=input;switch(toolName){case"Bash":return(obj?.command??"").split(`
868
868
  `)[0]?.trim()||null;case"Read":case"Write":case"Edit":return obj?.file_path||null;case"Grep":return obj?.pattern||null;case"Glob":return obj?.pattern||null;case"Agent":return obj?.subagent_type||null;case"Skill":return obj?.skill||null;default:return null}}function extractTextContent(content){if(typeof content==="string")return content;if(Array.isArray(content)){let texts=[];for(let block of content)if(typeof block==="string")texts.push(block);else if(block?.type==="text"&&typeof block.text==="string")texts.push(block.text);return texts.length>0?texts.join(`
869
- `):null}return null}async function discoverMainSession(filePath,projectPath,name){try{let st=await stat3(filePath);return{sessionId:basename2(name,".jsonl"),jsonlPath:filePath,projectPath,parentSessionId:null,isSubagent:!1,mtime:Math.floor(st.mtimeMs),fileSize:st.size}}catch{return null}}async function discoverSubagentSessions(projectPath,parentName){let results=[],subagentsDir=join24(projectPath,parentName,"subagents");try{let subFiles=await readdir4(subagentsDir);for(let subFile of subFiles){if(!subFile.endsWith(".jsonl"))continue;try{let filePath=join24(subagentsDir,subFile),st=await stat3(filePath);results.push({sessionId:basename2(subFile,".jsonl"),jsonlPath:filePath,projectPath,parentSessionId:parentName,isSubagent:!0,mtime:Math.floor(st.mtimeMs),fileSize:st.size})}catch{}}}catch{}return results}async function discoverProjectSessions(projectPath){let results=[];try{let entries=await readdir4(projectPath,{withFileTypes:!0});for(let entry of entries){if(entry.isFile()&&entry.name.endsWith(".jsonl")){let file=await discoverMainSession(join24(projectPath,entry.name),projectPath,entry.name);if(file)results.push(file);continue}if(entry.isDirectory()){let subs=await discoverSubagentSessions(projectPath,entry.name);results.push(...subs)}}}catch{}return results}async function discoverAllJsonlFiles(){let claudeDir=join24(process.env.CLAUDE_CONFIG_DIR??join24(homedir17(),".claude"),"projects"),projects;try{projects=await readdir4(claudeDir)}catch{return[]}let results=[];for(let project of projects){let files=await discoverProjectSessions(join24(claudeDir,project));results.push(...files)}return results}async function buildWorkerMap(sql){if(workerMapCache&&Date.now()<workerMapCache.expires)return workerMapCache.map;let map2=new Map;try{let rows=await sql`
869
+ `):null}return null}async function discoverMainSession(filePath,projectPath,name){try{let st=await stat3(filePath);return{sessionId:basename3(name,".jsonl"),jsonlPath:filePath,projectPath,parentSessionId:null,isSubagent:!1,mtime:Math.floor(st.mtimeMs),fileSize:st.size}}catch{return null}}async function discoverSubagentSessions(projectPath,parentName){let results=[],subagentsDir=join24(projectPath,parentName,"subagents");try{let subFiles=await readdir4(subagentsDir);for(let subFile of subFiles){if(!subFile.endsWith(".jsonl"))continue;try{let filePath=join24(subagentsDir,subFile),st=await stat3(filePath);results.push({sessionId:basename3(subFile,".jsonl"),jsonlPath:filePath,projectPath,parentSessionId:parentName,isSubagent:!0,mtime:Math.floor(st.mtimeMs),fileSize:st.size})}catch{}}}catch{}return results}async function discoverProjectSessions(projectPath){let results=[];try{let entries=await readdir4(projectPath,{withFileTypes:!0});for(let entry of entries){if(entry.isFile()&&entry.name.endsWith(".jsonl")){let file=await discoverMainSession(join24(projectPath,entry.name),projectPath,entry.name);if(file)results.push(file);continue}if(entry.isDirectory()){let subs=await discoverSubagentSessions(projectPath,entry.name);results.push(...subs)}}}catch{}return results}async function discoverAllJsonlFiles(){let claudeDir=join24(process.env.CLAUDE_CONFIG_DIR??join24(homedir17(),".claude"),"projects"),projects;try{projects=await readdir4(claudeDir)}catch{return[]}let results=[];for(let project of projects){let files=await discoverProjectSessions(join24(claudeDir,project));results.push(...files)}return results}async function buildWorkerMap(sql){if(workerMapCache&&Date.now()<workerMapCache.expires)return workerMapCache.map;let map2=new Map;try{let rows=await sql`
870
870
  SELECT e.id as executor_id, e.agent_id, e.claude_session_id, a.team, a.wish_slug, a.task_id, a.role
871
871
  FROM executors e
872
872
  JOIN agents a ON e.agent_id = a.id
@@ -1291,7 +1291,7 @@ Define your agent's mission here. What is their primary goal? What do they own?
1291
1291
  <constraints>
1292
1292
  - List any hard constraints or rules this agent must follow.
1293
1293
  </constraints>
1294
- `;var init_templates=()=>{};var exports_session={};__export(exports_session,{sessionCommand:()=>sessionCommand,sanitizeWindowName:()=>sanitizeWindowName,getAgentsFilePath:()=>getAgentsFilePath,buildClaudeCommand:()=>buildClaudeCommand2});import{spawnSync}from"child_process";import{createHash as createHash3}from"crypto";import{existsSync as existsSync22}from"fs";import{basename as basename3,join as join27}from"path";function shortPathHash(p){return createHash3("md5").update(p).digest("hex").slice(0,4)}function getAgentsFilePath(){let agentsPath=join27(process.cwd(),"AGENTS.md");if(existsSync22(agentsPath))return agentsPath;return null}async function ensureNativeTeamForLeader(teamName,cwd){await ensureNativeTeam(teamName,`Genie team: ${teamName}`,"pending"),await registerNativeMember(teamName,{agentName:basename3(cwd),agentType:"team-lead",color:"blue",cwd})}function buildClaudeCommand2(teamName,systemPromptFile,continueName){return buildTeamLeadCommand(teamName,{systemPromptFile,continueName})}async function registerSessionInRegistry(sessionName,windowName,workspaceDir){try{let target=`${sessionName}:${windowName}`,paneId=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_id}'`)).trim(),now=new Date().toISOString(),sanitized=sanitizeTeamName(windowName);await register({id:`${sanitized}-team-lead`,paneId,session:sessionName,team:windowName,role:"team-lead",worktree:null,startedAt:now,state:"working",lastStateChange:now,repoPath:workspaceDir,provider:"claude",transport:"tmux",nativeTeamEnabled:!0,nativeAgentId:`team-lead@${sanitized}`});let agentIdentity=await findOrCreateAgent("team-lead",sanitized,"team-lead");await terminateActiveExecutor(agentIdentity.id);let pid=null;try{let pidStr=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_pid}'`)).trim(),parsed=Number.parseInt(pidStr,10);if(parsed>0)pid=parsed}catch{}let executor=await createExecutor(agentIdentity.id,"claude","tmux",{pid,tmuxSession:sessionName,tmuxPaneId:paneId,tmuxWindow:windowName,state:"spawning",repoPath:workspaceDir});await setCurrentExecutor(agentIdentity.id,executor.id)}catch{}}async function resolveWindowName(sessionName,cwd){let baseName=sanitizeWindowName(basename3(cwd));if(!await findWindowByName(sessionName,baseName))return baseName;if(await getWindowEnv(`${sessionName}:${baseName}`,"GENIE_CWD")===cwd)return baseName;return`${baseName}-${shortPathHash(cwd)}`}async function createSession2(sessionName,windowName,workspaceDir,systemPromptFile){if(await ensureNativeTeamForLeader(windowName,workspaceDir),console.log(`Native team "${windowName}" ready at ~/.claude/teams/${sanitizeTeamName(windowName)}/`),console.log(`Creating session "${sessionName}"...`),!await createSession(sessionName))console.error(`Failed to create session "${sessionName}"`),process.exit(1);let firstWindow=(await listWindows(sessionName))[0];if(!firstWindow)console.error(`Failed to find initial window in session "${sessionName}"`),process.exit(1);await executeTmux2(`rename-window -t ${shellQuote(firstWindow.id)} ${shellQuote(windowName)}`),await executeTmux2(`set-window-option -t ${shellQuote(firstWindow.id)} automatic-rename off`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workspaceDir);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workspaceDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`);let agentName=basename3(workspaceDir),cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,void 0);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),console.log(`Started Claude Code as ${agentName} in ${workspaceDir}`),await registerSessionInRegistry(sessionName,windowName,workspaceDir)}async function launchWithContinueFallback(target,windowName,systemPromptFile){let continueName=sanitizeTeamName(windowName),hasPriorSession=sessionExists(continueName),cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,hasPriorSession?continueName:void 0);if(await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),hasPriorSession){await new Promise((r)=>setTimeout(r,3000));let afterCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(afterCmd)){console.log("Resume failed unexpectedly, starting fresh session...");let freshCmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,void 0);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(freshCmd)} Enter`)}}}async function focusTeamWindow(sessionName,windowName,workingDir,systemPromptFile){if((await ensureTeamWindow(sessionName,windowName,workingDir)).created){console.log(`Created team window "${windowName}"`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workingDir),await ensureNativeTeamForLeader(windowName,workingDir);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,systemPromptFile),console.log(`Started Claude Code as ${basename3(workingDir)}@${sanitizeTeamName(windowName)} in ${workingDir}`),await registerSessionInRegistry(sessionName,windowName,workingDir)}else{let target=`${sessionName}:${windowName}`,currentCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(currentCmd)){console.log(`Claude Code not running in "${windowName}", relaunching...`),await ensureNativeTeamForLeader(windowName,workingDir);let cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,systemPromptFile),await registerSessionInRegistry(sessionName,windowName,workingDir)}}await executeTmux2(`select-window -t ${shellQuote(`${sessionName}:${windowName}`)}`),console.log(`Focused team window "${windowName}"`)}function sanitizeWindowName(name){return name.replace(/\./g,"-")}async function deriveWindowName(sessionName,workspaceDir,team){if(team)return sanitizeWindowName(team);if(await findSessionByName(sessionName))return sanitizeWindowName(await resolveWindowName(sessionName,workspaceDir));return sanitizeWindowName(basename3(workspaceDir))}async function handleReset(sessionName,windowName){let existing=await findSessionByName(sessionName);if(existing){let windows=await listWindows(existing.id);console.log(`Resetting session "${sessionName}"...`),await killSession(existing.id),await Promise.all(windows.map((w)=>deleteNativeTeam(w.name)))}else await deleteNativeTeam(windowName)}function attachToWindow(sessionName,windowName){console.log("Attaching...");let target=`${sessionName}:${windowName}`,cmd=process.env.TMUX?"switch-client":"attach",{genieTmuxPrefix:genieTmuxPrefix2}=(init_tmux_wrapper(),__toCommonJS(exports_tmux_wrapper));spawnSync("tmux",[...genieTmuxPrefix2(),cmd,"-t",target],{stdio:"inherit"})}async function sessionCommand(options={}){let workspaceDir=options.dir??process.cwd(),sessionName=options.name??sanitizeWindowName(basename3(workspaceDir));try{let windowName=await deriveWindowName(sessionName,workspaceDir,options.team);if(options.reset)await handleReset(sessionName,windowName);let session=await findSessionByName(sessionName),systemPromptFile=getAgentsFilePath();if(!systemPromptFile)if(await esm_default2({message:"No agent found in this directory. Scaffold one?",default:!0}))scaffoldAgentFiles(workspaceDir),systemPromptFile=join27(workspaceDir,"AGENTS.md"),console.log("Created SOUL.md, HEARTBEAT.md, and AGENTS.md");else console.error("AGENTS.md required. Run `genie` again to scaffold."),process.exit(1);if(!session)await createSession2(sessionName,windowName,workspaceDir,systemPromptFile),attachToWindow(sessionName,windowName);else if(process.env.TMUX){let suffix=Date.now().toString(36).slice(-4),currentWindowName=`${windowName}-${suffix}`;await executeTmux2(`rename-window ${shellQuote(currentWindowName)}`),await ensureNativeTeamForLeader(currentWindowName,workspaceDir);let cmd=buildClaudeCommand2(currentWindowName,systemPromptFile||void 0,void 0),{execSync:execSyncCmd}=__require("child_process");execSyncCmd(cmd,{stdio:"inherit",cwd:workspaceDir})}else console.log(`Session "${sessionName}" already exists`),await focusTeamWindow(sessionName,windowName,workspaceDir,systemPromptFile),attachToWindow(sessionName,windowName)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}var init_session=__esm(()=>{init_esm6();init_agent_registry();init_claude_native_teams();init_executor_registry();init_team_lead_command();init_tmux();init_templates()});var exports_team_auto_spawn={};__export(exports_team_auto_spawn,{isTeamActive:()=>isTeamActive,ensureTeamLead:()=>ensureTeamLead});import{existsSync as existsSync23}from"fs";import{join as join28}from"path";function getSystemPromptFile(workingDir){let agentsPath=join28(workingDir,"AGENTS.md");if(existsSync23(agentsPath))return agentsPath;return null}async function ensureSession2(teamName){let current=await getCurrentSessionName();if(current)return current;let sessionName=sanitizeTeamName(teamName);if(await findSessionByName(sessionName))return sessionName;if(!await createSession(sessionName))throw Error(`Failed to create tmux session "${sessionName}"`);return sessionName}async function isTeamActive(teamName){if(!await loadConfig(teamName))return!1;let sessionName=await getCurrentSessionName()??sanitizeTeamName(teamName);if(!await findSessionByName(sessionName))return!1;try{let windows=await listWindows(sessionName),sanitized=sanitizeTeamName(teamName);return windows.some((w)=>w.name===sanitized||w.name===teamName)}catch{return!1}}async function ensureTeamLead(teamName,workingDir){let currentSession=await getCurrentSessionName()??sanitizeTeamName(teamName);if(await isTeamActive(teamName))return{created:!1,session:currentSession,window:sanitizeWindowName(teamName)};await ensureNativeTeam(teamName,`Genie team: ${teamName}`,"pending"),await registerNativeMember(teamName,{agentName:"team-lead",agentType:"general-purpose",color:"blue",cwd:workingDir});let session=await ensureSession2(teamName),windowName=sanitizeWindowName(teamName),teamWindow=await ensureTeamWindow(session,windowName,workingDir);if(teamWindow.created){let systemPromptFile=getSystemPromptFile(workingDir),target=`${session}:${windowName}`,cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`);let cmd=buildTeamLeadCommand(teamName,{systemPromptFile:systemPromptFile??void 0});await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`)}return{created:teamWindow.created,session,window:windowName}}var init_team_auto_spawn=__esm(()=>{init_session();init_claude_native_teams();init_team_lead_command();init_tmux()});var exports_inbox_watcher={};__export(exports_inbox_watcher,{stopInboxWatcher:()=>stopInboxWatcher,startInboxWatcher:()=>startInboxWatcher,resetSpawnFailures:()=>resetSpawnFailures,getInboxPollIntervalMs:()=>getInboxPollIntervalMs,checkInboxes:()=>checkInboxes});function getInboxPollIntervalMs(){let env=process.env.GENIE_INBOX_POLL_MS;if(env!==void 0){if(env==="")return INBOX_POLL_INTERVAL_MS;let parsed=Number(env);if(!Number.isNaN(parsed)&&parsed>=0)return parsed}return INBOX_POLL_INTERVAL_MS}function resetSpawnFailures(){spawnFailures.clear()}function resolveSessionKeyFromMessage(teamName,firstUnreadText){if(!firstUnreadText)return teamName;let header=parseRoutingHeader(firstUnreadText);return header?resolveSessionKey(teamName,header):teamName}async function checkInboxes(deps=defaultDeps2){if(getInboxPollIntervalMs()===0)return[];let teamsWithUnread=await deps.listTeamsWithUnreadInbox(),spawned=[];for(let{teamName,workingDir,firstUnreadText}of teamsWithUnread){let sessionKey=resolveSessionKeyFromMessage(teamName,firstUnreadText),failures=spawnFailures.get(sessionKey)??0;if(failures>=MAX_SPAWN_FAILURES){deps.warn(`[inbox-watcher] Skipping "${sessionKey}" \u2014 ${failures} consecutive spawn failures`);continue}if(await deps.isTeamActive(teamName))continue;if(!workingDir){deps.warn(`[inbox-watcher] Cannot spawn team-lead for "${teamName}" \u2014 no workingDir in config`);continue}try{await deps.ensureTeamLead(teamName,workingDir),spawnFailures.set(sessionKey,0),spawned.push(teamName)}catch(err){let newCount=failures+1;spawnFailures.set(sessionKey,newCount);let message=err instanceof Error?err.message:String(err);deps.warn(`[inbox-watcher] Failed to spawn team-lead for "${teamName}" (attempt ${newCount}/${MAX_SPAWN_FAILURES}): ${message}`)}}return spawned}function startInboxWatcher(deps=defaultDeps2){return setInterval(()=>{checkInboxes(deps).catch((err)=>{let message=err instanceof Error?err.message:String(err);deps.warn(`[inbox-watcher] Poll error: ${message}`)})},getInboxPollIntervalMs())}function stopInboxWatcher(handle){clearInterval(handle)}var defaultDeps2,INBOX_POLL_INTERVAL_MS=30000,MAX_SPAWN_FAILURES=3,spawnFailures;var init_inbox_watcher=__esm(()=>{init_claude_native_teams();init_routing_header();init_team_auto_spawn();defaultDeps2={listTeamsWithUnreadInbox,isTeamActive:(teamName)=>isTeamActive(teamName),ensureTeamLead:(teamName,workingDir)=>ensureTeamLead(teamName,workingDir),warn:(msg)=>console.warn(msg)};spawnFailures=new Map});function validateRunSpec(input){if(!input.command||input.command.trim().length===0)throw Error("RunSpec.command is required and cannot be empty");if(input.lease_timeout_ms!==void 0&&input.lease_timeout_ms<1e4)throw Error(`RunSpec.lease_timeout_ms must be >= 10000ms, got ${input.lease_timeout_ms}`);if(input.lease_timeout_ms!==void 0&&input.lease_timeout_ms>3600000)throw Error(`RunSpec.lease_timeout_ms must be <= 3600000ms (1h), got ${input.lease_timeout_ms}`);if(input.provider&&!VALID_PROVIDERS.has(input.provider))throw Error(`RunSpec.provider must be 'claude' or 'codex', got '${input.provider}'`);if(input.ref_policy&&!VALID_REF_POLICIES.has(input.ref_policy))throw Error(`RunSpec.ref_policy must be 'current' or 'default', got '${input.ref_policy}'`);if(input.approval_policy&&!VALID_APPROVAL_POLICIES.has(input.approval_policy))throw Error(`RunSpec.approval_policy must be 'auto' or 'manual', got '${input.approval_policy}'`)}function resolveRunSpec(input){return validateRunSpec(input),{repo:input.repo??DEFAULTS.repo,ref_policy:input.ref_policy??DEFAULTS.ref_policy,provider:input.provider??DEFAULTS.provider,role:input.role??DEFAULTS.role,model:input.model??DEFAULTS.model,command:input.command.trim(),approval_policy:input.approval_policy??DEFAULTS.approval_policy,concurrency_class:input.concurrency_class??DEFAULTS.concurrency_class,lease_timeout_ms:input.lease_timeout_ms??DEFAULTS.lease_timeout_ms}}var DEFAULTS,VALID_PROVIDERS,VALID_REF_POLICIES,VALID_APPROVAL_POLICIES;var init_run_spec=__esm(()=>{DEFAULTS={repo:process.cwd(),ref_policy:"current",provider:"claude",role:"worker",model:"",approval_policy:"auto",concurrency_class:"default",lease_timeout_ms:300000},VALID_PROVIDERS=new Set(["claude","codex"]),VALID_REF_POLICIES=new Set(["current","default"]),VALID_APPROVAL_POLICIES=new Set(["auto","manual"])});var exports_session_filewatch={};__export(exports_session_filewatch,{stopFilewatch:()=>stopFilewatch,startFilewatch:()=>startFilewatch});import{watch}from"fs";import{homedir as homedir18}from"os";import{basename as basename4,join as join29}from"path";async function loadOffsets(sql){try{let rows=await sql`SELECT id, last_ingested_offset FROM sessions WHERE last_ingested_offset > 0`;for(let row of rows)offsetCache.set(row.id,row.last_ingested_offset)}catch{}}function extractSessionInfo(filePath){if(!filePath.endsWith(".jsonl"))return null;let sessionId=basename4(filePath,".jsonl"),parts=filePath.split("/"),sessionsIdx=parts.lastIndexOf("sessions"),subagentsIdx=parts.lastIndexOf("subagents");if(subagentsIdx>0&&parts[subagentsIdx-1]){let parentSessionId=parts[subagentsIdx-1],projectIdx=parts.indexOf("projects"),projectPath=projectIdx>=0?parts.slice(0,projectIdx+2).join("/"):"";return{sessionId,projectPath,parentSessionId,isSubagent:!0}}if(sessionsIdx>0){let projectPath=parts.slice(0,sessionsIdx).join("/");return{sessionId,projectPath,parentSessionId:null,isSubagent:!1}}return null}async function handleFileChange(filePath,sql){let info=extractSessionInfo(filePath);if(!info)return;let storedOffset=offsetCache.get(info.sessionId)??0;try{setLiveWorkPending(!0);let workerMap=await buildWorkerMap(sql),result=await ingestFileFull(sql,info.sessionId,filePath,info.projectPath,storedOffset,{parentSessionId:info.parentSessionId,isSubagent:info.isSubagent,workerMap});offsetCache.set(info.sessionId,result.newOffset)}catch(err){let message=err instanceof Error?err.message:String(err);console.error(`[filewatch] error ingesting ${filePath} at offset ${storedOffset}: ${message}`)}finally{setLiveWorkPending(!1)}}async function startFilewatch(sql){if(watcher)return!0;let claudeDir=join29(process.env.CLAUDE_CONFIG_DIR??join29(homedir18(),".claude"),"projects");await loadOffsets(sql);try{return watcher=watch(claudeDir,{recursive:!0},(_eventType,filename)=>{if(!filename||!filename.endsWith(".jsonl"))return;let fullPath=join29(claudeDir,filename),existing=debounceTimers.get(fullPath);if(existing)clearTimeout(existing);debounceTimers.set(fullPath,setTimeout(()=>{debounceTimers.delete(fullPath),handleFileChange(fullPath,sql).catch((err)=>{let message=err instanceof Error?err.message:String(err);console.error(`[filewatch] unhandled error for ${fullPath}: ${message}`)})},DEBOUNCE_MS))}),watcher.on("error",(err)=>{console.error("[filewatch] watcher error:",err.message)}),console.log(`[filewatch] watching ${claudeDir} (${offsetCache.size} sessions cached)`),!0}catch(err){let message=err instanceof Error?err.message:String(err);return console.error(`[filewatch] failed to start: ${message}`),!1}}function stopFilewatch(){if(watcher)watcher.close(),watcher=null;for(let timer2 of debounceTimers.values())clearTimeout(timer2);debounceTimers.clear()}var watcher=null,offsetCache,debounceTimers,DEBOUNCE_MS=500;var init_session_filewatch=__esm(()=>{init_session_capture();offsetCache=new Map,debounceTimers=new Map});var exports_scheduler_daemon={};__export(exports_scheduler_daemon,{startDaemon:()=>startDaemon,recoverOnStartup:()=>recoverOnStartup,reconcileOrphans:()=>reconcileOrphans,reconcileOrphanedRuns:()=>reconcileOrphanedRuns,reclaimExpiredLeases:()=>reclaimExpiredLeases,logToFile:()=>logToFile,fireTrigger:()=>fireTrigger,emitWorkerEvents:()=>emitWorkerEvents,collectMachineSnapshot:()=>collectMachineSnapshot,collectHeartbeats:()=>collectHeartbeats,claimDueTriggers:()=>claimDueTriggers,attemptAgentResume:()=>attemptAgentResume,_resetWorkerStatesForTesting:()=>_resetWorkerStatesForTesting});import{randomUUID as randomUUID5}from"crypto";import{appendFileSync as appendFileSync2,mkdirSync as mkdirSync7}from"fs";import{homedir as homedir19}from"os";import{join as join30}from"path";function getLogDir2(){return join30(process.env.GENIE_HOME??join30(homedir19(),".genie"),"logs")}function getLogFile(){return join30(getLogDir2(),"scheduler.log")}function logToFile(entry){let logDir=getLogDir2();mkdirSync7(logDir,{recursive:!0}),appendFileSync2(getLogFile(),`${JSON.stringify(entry)}
1294
+ `;var init_templates=()=>{};var exports_session={};__export(exports_session,{sessionCommand:()=>sessionCommand,sanitizeWindowName:()=>sanitizeWindowName,getAgentsFilePath:()=>getAgentsFilePath,buildClaudeCommand:()=>buildClaudeCommand2});import{spawnSync}from"child_process";import{createHash as createHash3}from"crypto";import{existsSync as existsSync22}from"fs";import{basename as basename4,join as join27}from"path";function shortPathHash(p){return createHash3("md5").update(p).digest("hex").slice(0,4)}function getAgentsFilePath(){let agentsPath=join27(process.cwd(),"AGENTS.md");if(existsSync22(agentsPath))return agentsPath;return null}async function ensureNativeTeamForLeader(teamName,cwd){await ensureNativeTeam(teamName,`Genie team: ${teamName}`,"pending"),await registerNativeMember(teamName,{agentName:basename4(cwd),agentType:"team-lead",color:"blue",cwd})}function buildClaudeCommand2(teamName,systemPromptFile,continueName){return buildTeamLeadCommand(teamName,{systemPromptFile,continueName})}async function registerSessionInRegistry(sessionName,windowName,workspaceDir){try{let target=`${sessionName}:${windowName}`,paneId=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_id}'`)).trim(),now=new Date().toISOString(),sanitized=sanitizeTeamName(windowName);await register({id:`${sanitized}-team-lead`,paneId,session:sessionName,team:windowName,role:"team-lead",worktree:null,startedAt:now,state:"working",lastStateChange:now,repoPath:workspaceDir,provider:"claude",transport:"tmux",nativeTeamEnabled:!0,nativeAgentId:`team-lead@${sanitized}`});let agentIdentity=await findOrCreateAgent("team-lead",sanitized,"team-lead");await terminateActiveExecutor(agentIdentity.id);let pid=null;try{let pidStr=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_pid}'`)).trim(),parsed=Number.parseInt(pidStr,10);if(parsed>0)pid=parsed}catch{}let executor=await createExecutor(agentIdentity.id,"claude","tmux",{pid,tmuxSession:sessionName,tmuxPaneId:paneId,tmuxWindow:windowName,state:"spawning",repoPath:workspaceDir});await setCurrentExecutor(agentIdentity.id,executor.id)}catch{}}async function resolveWindowName(sessionName,cwd){let baseName=sanitizeWindowName(basename4(cwd));if(!await findWindowByName(sessionName,baseName))return baseName;if(await getWindowEnv(`${sessionName}:${baseName}`,"GENIE_CWD")===cwd)return baseName;return`${baseName}-${shortPathHash(cwd)}`}async function createSession2(sessionName,windowName,workspaceDir,systemPromptFile){if(await ensureNativeTeamForLeader(windowName,workspaceDir),console.log(`Native team "${windowName}" ready at ~/.claude/teams/${sanitizeTeamName(windowName)}/`),console.log(`Creating session "${sessionName}"...`),!await createSession(sessionName))console.error(`Failed to create session "${sessionName}"`),process.exit(1);let firstWindow=(await listWindows(sessionName))[0];if(!firstWindow)console.error(`Failed to find initial window in session "${sessionName}"`),process.exit(1);await executeTmux2(`rename-window -t ${shellQuote(firstWindow.id)} ${shellQuote(windowName)}`),await executeTmux2(`set-window-option -t ${shellQuote(firstWindow.id)} automatic-rename off`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workspaceDir);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workspaceDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`);let agentName=basename4(workspaceDir),cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,void 0);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),console.log(`Started Claude Code as ${agentName} in ${workspaceDir}`),await registerSessionInRegistry(sessionName,windowName,workspaceDir)}async function launchWithContinueFallback(target,windowName,systemPromptFile){let continueName=sanitizeTeamName(windowName),hasPriorSession=sessionExists(continueName),cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,hasPriorSession?continueName:void 0);if(await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),hasPriorSession){await new Promise((r)=>setTimeout(r,3000));let afterCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(afterCmd)){console.log("Resume failed unexpectedly, starting fresh session...");let freshCmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,void 0);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(freshCmd)} Enter`)}}}async function focusTeamWindow(sessionName,windowName,workingDir,systemPromptFile){if((await ensureTeamWindow(sessionName,windowName,workingDir)).created){console.log(`Created team window "${windowName}"`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workingDir),await ensureNativeTeamForLeader(windowName,workingDir);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,systemPromptFile),console.log(`Started Claude Code as ${basename4(workingDir)}@${sanitizeTeamName(windowName)} in ${workingDir}`),await registerSessionInRegistry(sessionName,windowName,workingDir)}else{let target=`${sessionName}:${windowName}`,currentCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(currentCmd)){console.log(`Claude Code not running in "${windowName}", relaunching...`),await ensureNativeTeamForLeader(windowName,workingDir);let cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,systemPromptFile),await registerSessionInRegistry(sessionName,windowName,workingDir)}}await executeTmux2(`select-window -t ${shellQuote(`${sessionName}:${windowName}`)}`),console.log(`Focused team window "${windowName}"`)}function sanitizeWindowName(name){return name.replace(/\./g,"-")}async function deriveWindowName(sessionName,workspaceDir,team){if(team)return sanitizeWindowName(team);if(await findSessionByName(sessionName))return sanitizeWindowName(await resolveWindowName(sessionName,workspaceDir));return sanitizeWindowName(basename4(workspaceDir))}async function handleReset(sessionName,windowName){let existing=await findSessionByName(sessionName);if(existing){let windows=await listWindows(existing.id);console.log(`Resetting session "${sessionName}"...`),await killSession(existing.id),await Promise.all(windows.map((w)=>deleteNativeTeam(w.name)))}else await deleteNativeTeam(windowName)}function attachToWindow(sessionName,windowName){console.log("Attaching...");let target=`${sessionName}:${windowName}`,cmd=process.env.TMUX?"switch-client":"attach",{genieTmuxPrefix:genieTmuxPrefix2}=(init_tmux_wrapper(),__toCommonJS(exports_tmux_wrapper));spawnSync("tmux",[...genieTmuxPrefix2(),cmd,"-t",target],{stdio:"inherit"})}async function sessionCommand(options={}){let workspaceDir=options.dir??process.cwd(),sessionName=options.name??sanitizeWindowName(basename4(workspaceDir));try{let windowName=await deriveWindowName(sessionName,workspaceDir,options.team);if(options.reset)await handleReset(sessionName,windowName);let session=await findSessionByName(sessionName),systemPromptFile=getAgentsFilePath();if(!systemPromptFile)if(await esm_default2({message:"No agent found in this directory. Scaffold one?",default:!0}))scaffoldAgentFiles(workspaceDir),systemPromptFile=join27(workspaceDir,"AGENTS.md"),console.log("Created SOUL.md, HEARTBEAT.md, and AGENTS.md");else console.error("AGENTS.md required. Run `genie` again to scaffold."),process.exit(1);if(!session)await createSession2(sessionName,windowName,workspaceDir,systemPromptFile),attachToWindow(sessionName,windowName);else if(process.env.TMUX){let suffix=Date.now().toString(36).slice(-4),currentWindowName=`${windowName}-${suffix}`;await executeTmux2(`rename-window ${shellQuote(currentWindowName)}`),await ensureNativeTeamForLeader(currentWindowName,workspaceDir);let cmd=buildClaudeCommand2(currentWindowName,systemPromptFile||void 0,void 0),{execSync:execSyncCmd}=__require("child_process");execSyncCmd(cmd,{stdio:"inherit",cwd:workspaceDir})}else console.log(`Session "${sessionName}" already exists`),await focusTeamWindow(sessionName,windowName,workspaceDir,systemPromptFile),attachToWindow(sessionName,windowName)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}var init_session=__esm(()=>{init_esm6();init_agent_registry();init_claude_native_teams();init_executor_registry();init_team_lead_command();init_tmux();init_templates()});var exports_team_auto_spawn={};__export(exports_team_auto_spawn,{isTeamActive:()=>isTeamActive,ensureTeamLead:()=>ensureTeamLead});import{existsSync as existsSync23}from"fs";import{join as join28}from"path";function getSystemPromptFile(workingDir){let agentsPath=join28(workingDir,"AGENTS.md");if(existsSync23(agentsPath))return agentsPath;return null}async function ensureSession2(teamName){let current=await getCurrentSessionName();if(current)return current;let{getTeam:getTeam3}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),teamConfig=await getTeam3(teamName);if(teamConfig?.tmuxSessionName){if(await findSessionByName(teamConfig.tmuxSessionName))return teamConfig.tmuxSessionName}let sessionName=sanitizeTeamName(teamName);if(await findSessionByName(sessionName))return sessionName;if(!await createSession(sessionName))throw Error(`Failed to create tmux session "${sessionName}"`);return sessionName}async function isTeamActive(teamName){if(!await loadConfig(teamName))return!1;let sessionName=await getCurrentSessionName()??sanitizeTeamName(teamName);if(!await findSessionByName(sessionName))return!1;try{let windows=await listWindows(sessionName),sanitized=sanitizeTeamName(teamName);return windows.some((w)=>w.name===sanitized||w.name===teamName)}catch{return!1}}async function ensureTeamLead(teamName,workingDir){let currentSession=await getCurrentSessionName()??sanitizeTeamName(teamName);if(await isTeamActive(teamName))return{created:!1,session:currentSession,window:sanitizeWindowName(teamName)};await ensureNativeTeam(teamName,`Genie team: ${teamName}`,"pending"),await registerNativeMember(teamName,{agentName:"team-lead",agentType:"general-purpose",color:"blue",cwd:workingDir});let session=await ensureSession2(teamName),windowName=sanitizeWindowName(teamName),teamWindow=await ensureTeamWindow(session,windowName,workingDir);if(teamWindow.created){let systemPromptFile=getSystemPromptFile(workingDir),target=`${session}:${windowName}`,cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`);let cmd=buildTeamLeadCommand(teamName,{systemPromptFile:systemPromptFile??void 0});await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`)}return{created:teamWindow.created,session,window:windowName}}var init_team_auto_spawn=__esm(()=>{init_session();init_claude_native_teams();init_team_lead_command();init_tmux()});var exports_inbox_watcher={};__export(exports_inbox_watcher,{stopInboxWatcher:()=>stopInboxWatcher,startInboxWatcher:()=>startInboxWatcher,resetSpawnFailures:()=>resetSpawnFailures,getInboxPollIntervalMs:()=>getInboxPollIntervalMs,checkInboxes:()=>checkInboxes});function getInboxPollIntervalMs(){let env=process.env.GENIE_INBOX_POLL_MS;if(env!==void 0){if(env==="")return INBOX_POLL_INTERVAL_MS;let parsed=Number(env);if(!Number.isNaN(parsed)&&parsed>=0)return parsed}return INBOX_POLL_INTERVAL_MS}function resetSpawnFailures(){spawnFailures.clear()}function resolveSessionKeyFromMessage(teamName,firstUnreadText){if(!firstUnreadText)return teamName;let header=parseRoutingHeader(firstUnreadText);return header?resolveSessionKey(teamName,header):teamName}async function checkInboxes(deps=defaultDeps2){if(getInboxPollIntervalMs()===0)return[];let teamsWithUnread=await deps.listTeamsWithUnreadInbox(),spawned=[];for(let{teamName,workingDir,firstUnreadText}of teamsWithUnread){let sessionKey=resolveSessionKeyFromMessage(teamName,firstUnreadText),failures=spawnFailures.get(sessionKey)??0;if(failures>=MAX_SPAWN_FAILURES){deps.warn(`[inbox-watcher] Skipping "${sessionKey}" \u2014 ${failures} consecutive spawn failures`);continue}if(await deps.isTeamActive(teamName))continue;if(!workingDir){deps.warn(`[inbox-watcher] Cannot spawn team-lead for "${teamName}" \u2014 no workingDir in config`);continue}try{await deps.ensureTeamLead(teamName,workingDir),spawnFailures.set(sessionKey,0),spawned.push(teamName)}catch(err){let newCount=failures+1;spawnFailures.set(sessionKey,newCount);let message=err instanceof Error?err.message:String(err);deps.warn(`[inbox-watcher] Failed to spawn team-lead for "${teamName}" (attempt ${newCount}/${MAX_SPAWN_FAILURES}): ${message}`)}}return spawned}function startInboxWatcher(deps=defaultDeps2){return setInterval(()=>{checkInboxes(deps).catch((err)=>{let message=err instanceof Error?err.message:String(err);deps.warn(`[inbox-watcher] Poll error: ${message}`)})},getInboxPollIntervalMs())}function stopInboxWatcher(handle){clearInterval(handle)}var defaultDeps2,INBOX_POLL_INTERVAL_MS=30000,MAX_SPAWN_FAILURES=3,spawnFailures;var init_inbox_watcher=__esm(()=>{init_claude_native_teams();init_routing_header();init_team_auto_spawn();defaultDeps2={listTeamsWithUnreadInbox,isTeamActive:(teamName)=>isTeamActive(teamName),ensureTeamLead:(teamName,workingDir)=>ensureTeamLead(teamName,workingDir),warn:(msg)=>console.warn(msg)};spawnFailures=new Map});function validateRunSpec(input){if(!input.command||input.command.trim().length===0)throw Error("RunSpec.command is required and cannot be empty");if(input.lease_timeout_ms!==void 0&&input.lease_timeout_ms<1e4)throw Error(`RunSpec.lease_timeout_ms must be >= 10000ms, got ${input.lease_timeout_ms}`);if(input.lease_timeout_ms!==void 0&&input.lease_timeout_ms>3600000)throw Error(`RunSpec.lease_timeout_ms must be <= 3600000ms (1h), got ${input.lease_timeout_ms}`);if(input.provider&&!VALID_PROVIDERS.has(input.provider))throw Error(`RunSpec.provider must be 'claude' or 'codex', got '${input.provider}'`);if(input.ref_policy&&!VALID_REF_POLICIES.has(input.ref_policy))throw Error(`RunSpec.ref_policy must be 'current' or 'default', got '${input.ref_policy}'`);if(input.approval_policy&&!VALID_APPROVAL_POLICIES.has(input.approval_policy))throw Error(`RunSpec.approval_policy must be 'auto' or 'manual', got '${input.approval_policy}'`)}function resolveRunSpec(input){return validateRunSpec(input),{repo:input.repo??DEFAULTS.repo,ref_policy:input.ref_policy??DEFAULTS.ref_policy,provider:input.provider??DEFAULTS.provider,role:input.role??DEFAULTS.role,model:input.model??DEFAULTS.model,command:input.command.trim(),approval_policy:input.approval_policy??DEFAULTS.approval_policy,concurrency_class:input.concurrency_class??DEFAULTS.concurrency_class,lease_timeout_ms:input.lease_timeout_ms??DEFAULTS.lease_timeout_ms}}var DEFAULTS,VALID_PROVIDERS,VALID_REF_POLICIES,VALID_APPROVAL_POLICIES;var init_run_spec=__esm(()=>{DEFAULTS={repo:process.cwd(),ref_policy:"current",provider:"claude",role:"worker",model:"",approval_policy:"auto",concurrency_class:"default",lease_timeout_ms:300000},VALID_PROVIDERS=new Set(["claude","codex"]),VALID_REF_POLICIES=new Set(["current","default"]),VALID_APPROVAL_POLICIES=new Set(["auto","manual"])});var exports_session_filewatch={};__export(exports_session_filewatch,{stopFilewatch:()=>stopFilewatch,startFilewatch:()=>startFilewatch});import{watch}from"fs";import{homedir as homedir18}from"os";import{basename as basename5,join as join29}from"path";async function loadOffsets(sql){try{let rows=await sql`SELECT id, last_ingested_offset FROM sessions WHERE last_ingested_offset > 0`;for(let row of rows)offsetCache.set(row.id,row.last_ingested_offset)}catch{}}function extractSessionInfo(filePath){if(!filePath.endsWith(".jsonl"))return null;let sessionId=basename5(filePath,".jsonl"),parts=filePath.split("/"),sessionsIdx=parts.lastIndexOf("sessions"),subagentsIdx=parts.lastIndexOf("subagents");if(subagentsIdx>0&&parts[subagentsIdx-1]){let parentSessionId=parts[subagentsIdx-1],projectIdx=parts.indexOf("projects"),projectPath=projectIdx>=0?parts.slice(0,projectIdx+2).join("/"):"";return{sessionId,projectPath,parentSessionId,isSubagent:!0}}if(sessionsIdx>0){let projectPath=parts.slice(0,sessionsIdx).join("/");return{sessionId,projectPath,parentSessionId:null,isSubagent:!1}}return null}async function handleFileChange(filePath,sql){let info=extractSessionInfo(filePath);if(!info)return;let storedOffset=offsetCache.get(info.sessionId)??0;try{setLiveWorkPending(!0);let workerMap=await buildWorkerMap(sql),result=await ingestFileFull(sql,info.sessionId,filePath,info.projectPath,storedOffset,{parentSessionId:info.parentSessionId,isSubagent:info.isSubagent,workerMap});offsetCache.set(info.sessionId,result.newOffset)}catch(err){let message=err instanceof Error?err.message:String(err);console.error(`[filewatch] error ingesting ${filePath} at offset ${storedOffset}: ${message}`)}finally{setLiveWorkPending(!1)}}async function startFilewatch(sql){if(watcher)return!0;let claudeDir=join29(process.env.CLAUDE_CONFIG_DIR??join29(homedir18(),".claude"),"projects");await loadOffsets(sql);try{return watcher=watch(claudeDir,{recursive:!0},(_eventType,filename)=>{if(!filename||!filename.endsWith(".jsonl"))return;let fullPath=join29(claudeDir,filename),existing=debounceTimers.get(fullPath);if(existing)clearTimeout(existing);debounceTimers.set(fullPath,setTimeout(()=>{debounceTimers.delete(fullPath),handleFileChange(fullPath,sql).catch((err)=>{let message=err instanceof Error?err.message:String(err);console.error(`[filewatch] unhandled error for ${fullPath}: ${message}`)})},DEBOUNCE_MS))}),watcher.on("error",(err)=>{console.error("[filewatch] watcher error:",err.message)}),console.log(`[filewatch] watching ${claudeDir} (${offsetCache.size} sessions cached)`),!0}catch(err){let message=err instanceof Error?err.message:String(err);return console.error(`[filewatch] failed to start: ${message}`),!1}}function stopFilewatch(){if(watcher)watcher.close(),watcher=null;for(let timer2 of debounceTimers.values())clearTimeout(timer2);debounceTimers.clear()}var watcher=null,offsetCache,debounceTimers,DEBOUNCE_MS=500;var init_session_filewatch=__esm(()=>{init_session_capture();offsetCache=new Map,debounceTimers=new Map});var exports_scheduler_daemon={};__export(exports_scheduler_daemon,{startDaemon:()=>startDaemon,recoverOnStartup:()=>recoverOnStartup,reconcileOrphans:()=>reconcileOrphans,reconcileOrphanedRuns:()=>reconcileOrphanedRuns,reclaimExpiredLeases:()=>reclaimExpiredLeases,logToFile:()=>logToFile,fireTrigger:()=>fireTrigger,emitWorkerEvents:()=>emitWorkerEvents,collectMachineSnapshot:()=>collectMachineSnapshot,collectHeartbeats:()=>collectHeartbeats,claimDueTriggers:()=>claimDueTriggers,attemptAgentResume:()=>attemptAgentResume,_resetWorkerStatesForTesting:()=>_resetWorkerStatesForTesting});import{randomUUID as randomUUID5}from"crypto";import{appendFileSync as appendFileSync2,mkdirSync as mkdirSync7}from"fs";import{homedir as homedir19}from"os";import{join as join30}from"path";function getLogDir2(){return join30(process.env.GENIE_HOME??join30(homedir19(),".genie"),"logs")}function getLogFile(){return join30(getLogDir2(),"scheduler.log")}function logToFile(entry){let logDir=getLogDir2();mkdirSync7(logDir,{recursive:!0}),appendFileSync2(getLogFile(),`${JSON.stringify(entry)}
1295
1295
  `)}async function defaultSpawnCommand(command,env){return{pid:Bun.spawn(["sh","-c",command],{env:{...process.env,...env},stdio:["ignore","ignore","ignore"]}).pid}}function defaultJitter(maxMs){return Math.floor(Math.random()*maxMs)}function defaultSleep(ms){return new Promise((resolve5)=>setTimeout(resolve5,ms))}async function defaultIsPaneAlive(paneId){let{isPaneAlive:isPaneAlive2}=await Promise.resolve().then(() => (init_tmux(),exports_tmux));return isPaneAlive2(paneId)}async function defaultListWorkers(){let{list:list2}=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry));return(await list2()).map((a)=>({id:a.id,paneId:a.paneId,repoPath:a.repoPath,state:a.state,team:a.team,wishSlug:a.wishSlug,groupNumber:a.groupNumber,autoResume:a.autoResume,resumeAttempts:a.resumeAttempts,maxResumeAttempts:a.maxResumeAttempts,lastResumeAttempt:a.lastResumeAttempt,claudeSessionId:a.claudeSessionId}))}async function defaultPublishEvent(subject,data,repoPath){let payload=data,{publishSubjectEvent:publishSubjectEvent2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events));await publishSubjectEvent2(repoPath,subject,{timestamp:payload.timestamp,kind:payload.kind??"system",agent:payload.agent??"scheduler",team:payload.team,direction:payload.direction,peer:payload.peer,text:payload.text??subject,data:payload.data,source:payload.source??"registry"})}async function defaultCountTmuxSessions(){try{let{execSync:execSync6}=await import("child_process"),{genieTmuxCmd:genieTmuxCmd2}=await Promise.resolve().then(() => (init_tmux_wrapper(),exports_tmux_wrapper));return execSync6(`${genieTmuxCmd2("list-sessions")} 2>/dev/null`,{encoding:"utf-8"}).trim().split(`
1296
1296
  `).filter(Boolean).length}catch{return 0}}async function defaultResumeAgent(agentId){try{let{execSync:execSync6}=await import("child_process");return execSync6(`genie agent resume ${agentId}`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}),!0}catch{return!1}}async function defaultUpdateAgent(agentId,updates){let{update:update2}=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry));await update2(agentId,updates)}function createDefaultDeps(){return{getConnection:async()=>{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return getConnection2()},spawnCommand:defaultSpawnCommand,log:logToFile,generateId:randomUUID5,now:()=>new Date,sleep:defaultSleep,jitter:defaultJitter,isPaneAlive:defaultIsPaneAlive,listWorkers:defaultListWorkers,countTmuxSessions:defaultCountTmuxSessions,publishEvent:defaultPublishEvent,resumeAgent:defaultResumeAgent,updateAgent:defaultUpdateAgent}}function resolveConfig(overrides){let envMax=process.env.GENIE_MAX_CONCURRENT,maxConcurrent=envMax?Number.parseInt(envMax,10):5;return{maxConcurrent:overrides?.maxConcurrent??(Number.isNaN(maxConcurrent)?5:maxConcurrent),pollIntervalMs:overrides?.pollIntervalMs??30000,maxJitterMs:overrides?.maxJitterMs??30000,jitterThreshold:overrides?.jitterThreshold??3,heartbeatIntervalMs:overrides?.heartbeatIntervalMs??60000,orphanCheckIntervalMs:overrides?.orphanCheckIntervalMs??300000,deadHeartbeatThreshold:overrides?.deadHeartbeatThreshold??2}}async function claimDueTriggers(deps,config,daemonId){let sql=await deps.getConnection(),now=deps.now(),leaseUntil=new Date(now.getTime()+300000),runningCount=(await sql`
1297
1297
  SELECT count(*)::int AS cnt FROM runs
@@ -1606,7 +1606,7 @@ ${answer}
1606
1606
  WHERE repo_path = ${repo}
1607
1607
  AND wish_file LIKE ${pattern}
1608
1608
  ORDER BY seq
1609
- `).map((r)=>({id:r.id,seq:r.seq,title:r.title,stage:r.stage,repoPath:r.repo_path}))}function getRepoPathSafe(){try{return execSync15("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}var init_task_close_merged=()=>{};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 resolve8,dirname as dirname10}from"path";import{fileURLToPath as fileURLToPath2}from"url";import{resolve as resolve22,isAbsolute,parse as parse2}from"path";import{existsSync as existsSync39}from"fs";import{basename as basename8,join as join50}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 writeFileSync15}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:
1609
+ `).map((r)=>({id:r.id,seq:r.seq,title:r.title,stage:r.stage,repoPath:r.repo_path}))}function getRepoPathSafe(){try{return execSync15("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}var init_task_close_merged=()=>{};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 resolve8,dirname as dirname10}from"path";import{fileURLToPath as fileURLToPath2}from"url";import{resolve as resolve22,isAbsolute,parse as parse2}from"path";import{existsSync as existsSync39}from"fs";import{basename as basename9,join as join50}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 writeFileSync15}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:
1610
1610
  `+treeLines.join(`
1611
1611
  `))}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(`
1612
1612
  `)}}function convertGlobalToLocalSelection(globalSelection,localX,localY){if(!globalSelection?.isActive)return null;return{anchorX:globalSelection.anchor.x-localX,anchorY:globalSelection.anchor.y-localY,focusX:globalSelection.focus.x-localX,focusY:globalSelection.focus.y-localY,isActive:!0}}class ASCIIFontSelectionHelper{getText;getFont;localSelection=null;constructor(getText,getFont){this.getText=getText,this.getFont=getFont}hasSelection(){return this.localSelection!==null}getSelection(){return this.localSelection}shouldStartSelection(localX,localY,width,height2){if(localX<0||localX>=width||localY<0||localY>=height2)return!1;let text=this.getText(),font=this.getFont(),charIndex=coordinateToCharacterIndex(localX,text,font);return charIndex>=0&&charIndex<=text.length}onLocalSelectionChanged(localSelection,width,height2){let previousSelection=this.localSelection;if(!localSelection?.isActive)return this.localSelection=null,previousSelection!==null;let text=this.getText(),font=this.getFont(),selStart={x:localSelection.anchorX,y:localSelection.anchorY},selEnd={x:localSelection.focusX,y:localSelection.focusY};if(height2-1<selStart.y||0>selEnd.y)return this.localSelection=null,previousSelection!==null;let startCharIndex=0,endCharIndex=text.length;if(selStart.y>height2-1)return this.localSelection=null,previousSelection!==null;else if(selStart.y>=0&&selStart.y<=height2-1){if(selStart.x>0)startCharIndex=coordinateToCharacterIndex(selStart.x,text,font)}if(selEnd.y<0)return this.localSelection=null,previousSelection!==null;else if(selEnd.y>=0&&selEnd.y<=height2-1)if(selEnd.x>=0)endCharIndex=coordinateToCharacterIndex(selEnd.x,text,font);else endCharIndex=0;if(startCharIndex<endCharIndex&&startCharIndex>=0&&endCharIndex<=text.length)this.localSelection={start:startCharIndex,end:endCharIndex};else this.localSelection=null;return previousSelection?.start!==this.localSelection?.start||previousSelection?.end!==this.localSelection?.end}}function singleton(key,factory){let bag=globalThis[singletonCacheSymbol]??={};if(!(key in bag))bag[key]=factory();return bag[key]}function destroySingleton(key){let bag=globalThis[singletonCacheSymbol];if(bag&&key in bag)delete bag[key]}function hasSingleton(key){let bag=globalThis[singletonCacheSymbol];return bag&&key in bag}function registerEnvVar(config){let existing=envRegistry[config.name];if(existing){if(existing.description!==config.description||existing.type!==config.type||existing.default!==config.default)throw Error(`Environment variable "${config.name}" is already registered with different configuration. Existing: ${JSON.stringify(existing)}, New: ${JSON.stringify(config)}`);return}envRegistry[config.name]=config}function normalizeBoolean(value){let lowerValue=value.toLowerCase();return["true","1","on","yes"].includes(lowerValue)}function parseEnvValue(config){let envValue=process.env[config.name];if(envValue===void 0&&config.default!==void 0)return config.default;if(envValue===void 0)throw Error(`Required environment variable ${config.name} is not set. ${config.description}`);switch(config.type){case"boolean":return typeof envValue==="boolean"?envValue:normalizeBoolean(envValue);case"number":let numValue=Number(envValue);if(isNaN(numValue))throw Error(`Environment variable ${config.name} must be a valid number, got: ${envValue}`);return numValue;case"string":default:return envValue}}class EnvStore{parsedValues=new Map;get(key){if(this.parsedValues.has(key))return this.parsedValues.get(key);if(!(key in envRegistry))throw Error(`Environment variable ${key} is not registered.`);try{let value=parseEnvValue(envRegistry[key]);return this.parsedValues.set(key,value),value}catch(error2){throw Error(`Failed to parse env var ${key}: ${error2 instanceof Error?error2.message:String(error2)}`)}}has(key){return key in envRegistry}clearCache(){this.parsedValues.clear()}}function clearEnvCache(){envStore.clearCache()}function generateEnvMarkdown(){let configs=Object.values(envRegistry);if(configs.length===0)return`# Environment Variables
@@ -1634,7 +1634,7 @@ No environment variables registered.
1634
1634
  `}else output+=`\x1B[32mDefault:\x1B[0m \x1B[31mRequired\x1B[0m
1635
1635
  `;output+=`
1636
1636
  `}return output}class ByteQueue{buf;start=0;end=0;constructor(capacity=INITIAL_PENDING_CAPACITY){this.buf=new Uint8Array(capacity)}get length(){return this.end-this.start}get capacity(){return this.buf.length}view(){return this.buf.subarray(this.start,this.end)}take(){let chunk=this.view();return this.start=0,this.end=0,chunk}append(chunk){if(chunk.length===0)return;this.ensureCapacity(this.length+chunk.length),this.buf.set(chunk,this.end),this.end+=chunk.length}consume(count){if(count<=0)return;if(count>=this.length){this.start=0,this.end=0;return}if(this.start+=count,this.start>=this.buf.length/2)this.buf.copyWithin(0,this.start,this.end),this.end-=this.start,this.start=0}clear(){this.start=0,this.end=0}reset(capacity=INITIAL_PENDING_CAPACITY){this.buf=new Uint8Array(capacity),this.start=0,this.end=0}ensureCapacity(requiredLength){let currentLength=this.length;if(requiredLength<=this.buf.length){if(this.buf.length-this.end>=requiredLength-currentLength)return;if(this.buf.copyWithin(0,this.start,this.end),this.end=currentLength,this.start=0,requiredLength<=this.buf.length)return}let nextCapacity=this.buf.length;while(nextCapacity<requiredLength)nextCapacity*=2;let next=new Uint8Array(nextCapacity);next.set(this.view(),0),this.buf=next,this.start=0,this.end=currentLength}}function normalizePositiveOption(value,fallback){if(typeof value!=="number"||!Number.isFinite(value)||value<=0)return fallback;return Math.floor(value)}function utf8SequenceLength(first){if(first<128)return 1;if(first>=194&&first<=223)return 2;if(first>=224&&first<=239)return 3;if(first>=240&&first<=244)return 4;return 0}function bytesEqual(left,right){if(left.length!==right.length)return!1;for(let index=0;index<left.length;index+=1)if(left[index]!==right[index])return!1;return!0}function isMouseSgrSequence(sequence){if(sequence.length<7)return!1;if(sequence[0]!==ESC||sequence[1]!==91||sequence[2]!==60)return!1;let final=sequence[sequence.length-1];if(final!==77&&final!==109)return!1;let part=0,hasDigit=!1;for(let index=3;index<sequence.length-1;index+=1){let byte=sequence[index];if(byte>=48&&byte<=57){hasDigit=!0;continue}if(byte===59&&hasDigit&&part<2){part+=1,hasDigit=!1;continue}return!1}return part===2&&hasDigit}function isAsciiDigit(byte){return byte>=48&&byte<=57}function parsePositiveDecimalPrefix(sequence,start2,endExclusive){if(start2>=endExclusive)return null;let value=0,sawDigit=!1;for(let index=start2;index<endExclusive;index+=1){let byte=sequence[index];if(!isAsciiDigit(byte))return null;sawDigit=!0,value=value*10+(byte-48)}return sawDigit?value:null}function canStillBeKittyU(state){return state.semicolons>=1}function canStillBeKittySpecial(state){return state.semicolons===1&&state.segments>1}function canStillBeExplicitWidthCpr(state){return state.firstParamValue===1&&state.semicolons===1}function canStillBePixelResolution(state){return state.firstParamValue===4&&state.semicolons===2}function canDeferParametricCsi(state,context){return context.kittyKeyboardEnabled&&(canStillBeKittyU(state)||canStillBeKittySpecial(state))||context.explicitWidthCprActive&&canStillBeExplicitWidthCpr(state)||context.pixelResolutionQueryActive&&canStillBePixelResolution(state)}function canCompleteDeferredParametricCsi(state,byte,context){if(context.kittyKeyboardEnabled){if(state.hasDigit&&byte===117)return!0;if(state.hasDigit&&state.semicolons===1&&state.segments>1&&(byte===126||byte>=65&&byte<=90))return!0}if(context.explicitWidthCprActive&&state.hasDigit&&state.firstParamValue===1&&state.semicolons===1&&byte===82)return!0;if(context.pixelResolutionQueryActive&&state.hasDigit&&state.firstParamValue===4&&state.semicolons===2&&byte===116)return!0;return!1}function canDeferPrivateReplyCsi(context){return context.privateCapabilityRepliesActive}function canCompleteDeferredPrivateReplyCsi(state,byte,context){if(!context.privateCapabilityRepliesActive)return!1;if(state.sawDollar)return state.hasDigit&&byte===121;if(byte===99)return state.hasDigit||state.semicolons>0;return state.hasDigit&&byte===117}function concatBytes(left,right){if(left.length===0)return right;if(right.length===0)return left;let combined=new Uint8Array(left.length+right.length);return combined.set(left,0),combined.set(right,left.length),combined}function indexOfBytes(haystack,needle){if(needle.length===0)return 0;let limit=haystack.length-needle.length;for(let offset=0;offset<=limit;offset+=1){let matched=!0;for(let index=0;index<needle.length;index+=1)if(haystack[offset+index]!==needle[index]){matched=!1;break}if(matched)return offset}return-1}function decodeLatin1(bytes){return Buffer3.from(bytes.buffer,bytes.byteOffset,bytes.byteLength).toString("latin1")}function decodeUtf8(bytes){return KEY_DECODER.decode(bytes)}function createPasteCollector(){return{tail:EMPTY_BYTES,parts:[],totalLength:0}}function joinPasteBytes(parts,totalLength){if(totalLength===0)return EMPTY_BYTES;if(parts.length===1)return parts[0];let bytes=new Uint8Array(totalLength),offset=0;for(let part of parts)bytes.set(part,offset),offset+=part.length;return bytes}class StdinParser{pending=new ByteQueue(INITIAL_PENDING_CAPACITY);events=[];timeoutMs;maxPendingBytes;armTimeouts;onTimeoutFlush;useKittyKeyboard;mouseParser=new MouseParser;clock;protocolContext;timeoutId=null;destroyed=!1;pendingSinceMs=null;forceFlush=!1;justFlushedEsc=!1;state={tag:"ground"};cursor=0;unitStart=0;paste=null;constructor(options={}){this.timeoutMs=normalizePositiveOption(options.timeoutMs,DEFAULT_TIMEOUT_MS),this.maxPendingBytes=normalizePositiveOption(options.maxPendingBytes,DEFAULT_MAX_PENDING_BYTES),this.armTimeouts=options.armTimeouts??!0,this.onTimeoutFlush=options.onTimeoutFlush??null,this.useKittyKeyboard=options.useKittyKeyboard??!0,this.clock=options.clock??SYSTEM_CLOCK,this.protocolContext={...DEFAULT_PROTOCOL_CONTEXT,kittyKeyboardEnabled:options.protocolContext?.kittyKeyboardEnabled??!1,privateCapabilityRepliesActive:options.protocolContext?.privateCapabilityRepliesActive??!1,pixelResolutionQueryActive:options.protocolContext?.pixelResolutionQueryActive??!1,explicitWidthCprActive:options.protocolContext?.explicitWidthCprActive??!1}}get bufferCapacity(){return this.pending.capacity}updateProtocolContext(patch){this.ensureAlive(),this.protocolContext={...this.protocolContext,...patch},this.reconcileDeferredStateWithProtocolContext(),this.reconcileTimeoutState()}push(data){if(this.ensureAlive(),data.length===0){this.emitKeyOrResponse("unknown","");return}let remainder=data;while(remainder.length>0){if(this.paste){remainder=this.consumePasteBytes(remainder);continue}let immediatePasteStartIndex=this.state.tag==="ground"&&this.pending.length===0?indexOfBytes(remainder,BRACKETED_PASTE_START):-1,appendEnd=immediatePasteStartIndex===-1?remainder.length:immediatePasteStartIndex+BRACKETED_PASTE_START.length;if(this.pending.append(remainder.subarray(0,appendEnd)),remainder=remainder.subarray(appendEnd),this.scanPending(),this.paste&&this.pending.length>0){remainder=this.consumePasteBytes(this.takePendingBytes());continue}if(!this.paste&&this.pending.length>this.maxPendingBytes){if(this.flushPendingOverflow(),this.scanPending(),this.paste&&this.pending.length>0)remainder=this.consumePasteBytes(this.takePendingBytes())}}this.reconcileTimeoutState()}read(){if(this.ensureAlive(),this.events.length===0&&this.forceFlush)this.scanPending(),this.reconcileTimeoutState();return this.events.shift()??null}drain(onEvent){this.ensureAlive();while(!0){if(this.destroyed)return;let event=this.read();if(!event)return;onEvent(event)}}flushTimeout(nowMsValue=this.clock.now()){if(this.ensureAlive(),this.paste||this.pendingSinceMs===null||this.pending.length===0)return;if(nowMsValue<this.pendingSinceMs||nowMsValue-this.pendingSinceMs<this.timeoutMs)return;this.forceFlush=!0}reset(){if(this.destroyed)return;this.clearTimeout(),this.resetState()}resetMouseState(){this.ensureAlive(),this.mouseParser.reset()}destroy(){if(this.destroyed)return;this.clearTimeout(),this.destroyed=!0,this.resetState()}ensureAlive(){if(this.destroyed)throw Error("StdinParser has been destroyed")}scanPending(){while(!this.paste){let bytes=this.pending.view();if(this.state.tag==="ground"&&this.cursor>=bytes.length){this.pending.clear(),this.cursor=0,this.unitStart=0,this.pendingSinceMs=null,this.forceFlush=!1;return}let byte=this.cursor<bytes.length?bytes[this.cursor]:-1;switch(this.state.tag){case"ground":{if(this.unitStart=this.cursor,this.justFlushedEsc){if(byte===91){this.justFlushedEsc=!1,this.cursor+=1,this.state={tag:"esc_recovery"};continue}this.justFlushedEsc=!1}if(byte===ESC){this.cursor+=1,this.state={tag:"esc"};continue}if(byte<128){this.emitKeyOrResponse("unknown",decodeUtf8(bytes.subarray(this.cursor,this.cursor+1))),this.consumePrefix(this.cursor+1);continue}let expected=utf8SequenceLength(byte);if(expected===0){if(!this.forceFlush&&this.cursor+1===bytes.length){this.markPending();return}this.emitLegacyHighByte(byte),this.consumePrefix(this.cursor+1);continue}this.cursor+=1,this.state={tag:"utf8",expected,seen:1};continue}case"utf8":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitLegacyHighByte(bytes[this.unitStart]),this.state={tag:"ground"},this.consumePrefix(this.unitStart+1);continue}if((byte&192)!==128){this.emitLegacyHighByte(bytes[this.unitStart]),this.state={tag:"ground"},this.consumePrefix(this.unitStart+1);continue}let nextSeen=this.state.seen+1;if(this.cursor+=1,nextSeen<this.state.expected){this.state={tag:"utf8",expected:this.state.expected,seen:nextSeen};continue}this.emitKeyOrResponse("unknown",decodeUtf8(bytes.subarray(this.unitStart,this.cursor))),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}case"esc":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}let flushedLoneEsc=this.cursor===this.unitStart+1&&bytes[this.unitStart]===ESC;this.emitKeyOrResponse("unknown",decodeUtf8(bytes.subarray(this.unitStart,this.cursor))),this.justFlushedEsc=flushedLoneEsc,this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}switch(byte){case 91:this.cursor+=1,this.state={tag:"csi"};continue;case 79:this.cursor+=1,this.state={tag:"ss3"};continue;case 93:this.cursor+=1,this.state={tag:"osc",sawEsc:!1};continue;case 80:this.cursor+=1,this.state={tag:"dcs",sawEsc:!1};continue;case 95:this.cursor+=1,this.state={tag:"apc",sawEsc:!1};continue;case ESC:this.cursor+=1;continue;default:this.cursor+=1,this.emitKeyOrResponse("unknown",decodeUtf8(bytes.subarray(this.unitStart,this.cursor))),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}}case"ss3":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}this.cursor+=1,this.emitKeyOrResponse("unknown",decodeUtf8(bytes.subarray(this.unitStart,this.cursor))),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}case"esc_recovery":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitKeyOrResponse("unknown",decodeUtf8(bytes.subarray(this.unitStart,this.cursor))),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte===60){this.cursor+=1,this.state={tag:"esc_less_mouse"};continue}if(byte===77){this.cursor+=1,this.state={tag:"esc_less_x10_mouse"};continue}this.emitKeyOrResponse("unknown",decodeUtf8(bytes.subarray(this.unitStart,this.unitStart+1))),this.state={tag:"ground"},this.consumePrefix(this.unitStart+1);continue}case"csi":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte===77&&this.cursor===this.unitStart+2){let end=this.cursor+4;if(bytes.length<end){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,bytes.length)),this.state={tag:"ground"},this.consumePrefix(bytes.length);continue}this.emitMouse(bytes.subarray(this.unitStart,end),"x10"),this.state={tag:"ground"},this.consumePrefix(end);continue}if(byte===36){let candidateEnd=this.cursor+1,candidate=decodeUtf8(bytes.subarray(this.unitStart,candidateEnd));if(RXVT_DOLLAR_CSI_RE.test(candidate)){this.emitKeyOrResponse("csi",candidate),this.state={tag:"ground"},this.consumePrefix(candidateEnd);continue}if(!this.forceFlush&&candidateEnd>=bytes.length){this.markPending();return}}if(byte===60&&this.cursor===this.unitStart+2){this.cursor+=1,this.state={tag:"csi_sgr_mouse",part:0,hasDigit:!1};continue}if(byte===91&&this.cursor===this.unitStart+2){this.cursor+=1;continue}if(byte===63&&this.cursor===this.unitStart+2){this.cursor+=1,this.state={tag:"csi_private_reply",semicolons:0,hasDigit:!1,sawDollar:!1};continue}if(byte===59){let firstParamValue=parsePositiveDecimalPrefix(bytes,this.unitStart+2,this.cursor);if(firstParamValue!==null){this.cursor+=1,this.state={tag:"csi_parametric",semicolons:1,segments:1,hasDigit:!1,firstParamValue};continue}}if(byte>=64&&byte<=126){let end=this.cursor+1,rawBytes=bytes.subarray(this.unitStart,end);if(bytesEqual(rawBytes,BRACKETED_PASTE_START)){this.state={tag:"ground"},this.consumePrefix(end),this.paste=createPasteCollector();continue}if(isMouseSgrSequence(rawBytes)){this.emitMouse(rawBytes,"sgr"),this.state={tag:"ground"},this.consumePrefix(end);continue}this.emitKeyOrResponse("csi",decodeUtf8(rawBytes)),this.state={tag:"ground"},this.consumePrefix(end);continue}this.cursor+=1;continue}case"csi_sgr_mouse":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.state={tag:"csi_sgr_mouse_deferred",part:this.state.part,hasDigit:this.state.hasDigit},this.pendingSinceMs=null,this.forceFlush=!1;return}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(isAsciiDigit(byte)){this.cursor+=1,this.state={tag:"csi_sgr_mouse",part:this.state.part,hasDigit:!0};continue}if(byte===59&&this.state.hasDigit&&this.state.part<2){this.cursor+=1,this.state={tag:"csi_sgr_mouse",part:this.state.part+1,hasDigit:!1};continue}if(byte>=64&&byte<=126){let end=this.cursor+1,rawBytes=bytes.subarray(this.unitStart,end);if(isMouseSgrSequence(rawBytes))this.emitMouse(rawBytes,"sgr");else this.emitKeyOrResponse("csi",decodeUtf8(rawBytes));this.state={tag:"ground"},this.consumePrefix(end);continue}this.state={tag:"csi"};continue}case"csi_sgr_mouse_deferred":{if(this.cursor>=bytes.length){this.pendingSinceMs=null,this.forceFlush=!1;return}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(isAsciiDigit(byte)||byte===59||byte===77||byte===109){this.state={tag:"csi_sgr_mouse",part:this.state.part,hasDigit:this.state.hasDigit};continue}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}case"csi_parametric":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}if(canDeferParametricCsi(this.state,this.protocolContext)){this.state={tag:"csi_parametric_deferred",semicolons:this.state.semicolons,segments:this.state.segments,hasDigit:this.state.hasDigit,firstParamValue:this.state.firstParamValue},this.pendingSinceMs=null,this.forceFlush=!1;return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(isAsciiDigit(byte)){this.cursor+=1,this.state={tag:"csi_parametric",semicolons:this.state.semicolons,segments:this.state.segments,hasDigit:!0,firstParamValue:this.state.firstParamValue};continue}if(byte===58&&this.state.hasDigit&&this.state.segments<3){this.cursor+=1,this.state={tag:"csi_parametric",semicolons:this.state.semicolons,segments:this.state.segments+1,hasDigit:!1,firstParamValue:this.state.firstParamValue};continue}if(byte===59&&this.state.semicolons<2){this.cursor+=1,this.state={tag:"csi_parametric",semicolons:this.state.semicolons+1,segments:1,hasDigit:!1,firstParamValue:this.state.firstParamValue};continue}if(byte>=64&&byte<=126){let end=this.cursor+1;this.emitKeyOrResponse("csi",decodeUtf8(bytes.subarray(this.unitStart,end))),this.state={tag:"ground"},this.consumePrefix(end);continue}this.state={tag:"csi"};continue}case"csi_parametric_deferred":{if(this.cursor>=bytes.length){this.pendingSinceMs=null,this.forceFlush=!1;return}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(isAsciiDigit(byte)||byte===58||byte===59){this.state={tag:"csi_parametric",semicolons:this.state.semicolons,segments:this.state.segments,hasDigit:this.state.hasDigit,firstParamValue:this.state.firstParamValue};continue}if(canCompleteDeferredParametricCsi(this.state,byte,this.protocolContext)){this.state={tag:"csi_parametric",semicolons:this.state.semicolons,segments:this.state.segments,hasDigit:this.state.hasDigit,firstParamValue:this.state.firstParamValue};continue}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}case"csi_private_reply":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}if(canDeferPrivateReplyCsi(this.protocolContext)){this.state={tag:"csi_private_reply_deferred",semicolons:this.state.semicolons,hasDigit:this.state.hasDigit,sawDollar:this.state.sawDollar},this.pendingSinceMs=null,this.forceFlush=!1;return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(isAsciiDigit(byte)){this.cursor+=1,this.state={tag:"csi_private_reply",semicolons:this.state.semicolons,hasDigit:!0,sawDollar:this.state.sawDollar};continue}if(byte===59){this.cursor+=1,this.state={tag:"csi_private_reply",semicolons:this.state.semicolons+1,hasDigit:!1,sawDollar:!1};continue}if(byte===36&&this.state.hasDigit&&!this.state.sawDollar){this.cursor+=1,this.state={tag:"csi_private_reply",semicolons:this.state.semicolons,hasDigit:!0,sawDollar:!0};continue}if(byte>=64&&byte<=126){let end=this.cursor+1;this.emitKeyOrResponse("csi",decodeUtf8(bytes.subarray(this.unitStart,end))),this.state={tag:"ground"},this.consumePrefix(end);continue}this.state={tag:"csi"};continue}case"csi_private_reply_deferred":{if(this.cursor>=bytes.length){this.pendingSinceMs=null,this.forceFlush=!1;return}if(byte===ESC){this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(isAsciiDigit(byte)||byte===59||byte===36){this.state={tag:"csi_private_reply",semicolons:this.state.semicolons,hasDigit:this.state.hasDigit,sawDollar:this.state.sawDollar};continue}if(canCompleteDeferredPrivateReplyCsi(this.state,byte,this.protocolContext)){this.state={tag:"csi_private_reply",semicolons:this.state.semicolons,hasDigit:this.state.hasDigit,sawDollar:this.state.sawDollar};continue}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}case"osc":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(this.state.sawEsc){if(byte===92){let end=this.cursor+1;this.emitOpaqueResponse("osc",bytes.subarray(this.unitStart,end)),this.state={tag:"ground"},this.consumePrefix(end);continue}this.state={tag:"osc",sawEsc:!1};continue}if(byte===BEL){let end=this.cursor+1;this.emitOpaqueResponse("osc",bytes.subarray(this.unitStart,end)),this.state={tag:"ground"},this.consumePrefix(end);continue}if(byte===ESC){this.cursor+=1,this.state={tag:"osc",sawEsc:!0};continue}this.cursor+=1;continue}case"dcs":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(this.state.sawEsc){if(byte===92){let end=this.cursor+1;this.emitOpaqueResponse("dcs",bytes.subarray(this.unitStart,end)),this.state={tag:"ground"},this.consumePrefix(end);continue}this.state={tag:"dcs",sawEsc:!1};continue}if(byte===ESC){this.cursor+=1,this.state={tag:"dcs",sawEsc:!0};continue}this.cursor+=1;continue}case"apc":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(this.state.sawEsc){if(byte===92){let end=this.cursor+1;this.emitOpaqueResponse("apc",bytes.subarray(this.unitStart,end)),this.state={tag:"ground"},this.consumePrefix(end);continue}this.state={tag:"apc",sawEsc:!1};continue}if(byte===ESC){this.cursor+=1,this.state={tag:"apc",sawEsc:!0};continue}this.cursor+=1;continue}case"esc_less_mouse":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte>=48&&byte<=57||byte===59){this.cursor+=1;continue}if(byte===77||byte===109){let end=this.cursor+1;this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,end)),this.state={tag:"ground"},this.consumePrefix(end);continue}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}case"esc_less_x10_mouse":{let end=this.unitStart+5;if(bytes.length<end){if(!this.forceFlush){this.markPending();return}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,bytes.length)),this.state={tag:"ground"},this.consumePrefix(bytes.length);continue}this.emitOpaqueResponse("unknown",bytes.subarray(this.unitStart,end)),this.state={tag:"ground"},this.consumePrefix(end);continue}}}}emitKeyOrResponse(protocol,raw){let parsed=parseKeypress(raw,{useKittyKeyboard:this.useKittyKeyboard});if(parsed){this.events.push({type:"key",raw:parsed.raw,key:parsed});return}this.events.push({type:"response",protocol,sequence:raw})}emitMouse(rawBytes,encoding){let event=this.mouseParser.parseMouseEvent(rawBytes);if(!event){this.emitOpaqueResponse("unknown",rawBytes);return}this.events.push({type:"mouse",raw:decodeLatin1(rawBytes),encoding,event})}emitLegacyHighByte(byte){let parsed=parseKeypress(Buffer3.from([byte]),{useKittyKeyboard:this.useKittyKeyboard});if(parsed){this.events.push({type:"key",raw:parsed.raw,key:parsed});return}this.events.push({type:"response",protocol:"unknown",sequence:String.fromCharCode(byte)})}emitOpaqueResponse(protocol,rawBytes){this.events.push({type:"response",protocol,sequence:decodeLatin1(rawBytes)})}consumePrefix(endExclusive){this.pending.consume(endExclusive),this.cursor=0,this.unitStart=0,this.pendingSinceMs=null,this.forceFlush=!1}takePendingBytes(){let buffered=this.pending.take();return this.cursor=0,this.unitStart=0,this.pendingSinceMs=null,this.forceFlush=!1,buffered}flushPendingOverflow(){if(this.pending.length===0)return;this.emitOpaqueResponse("unknown",this.pending.view()),this.pending.clear(),this.cursor=0,this.unitStart=0,this.pendingSinceMs=null,this.forceFlush=!1,this.state={tag:"ground"}}markPending(){this.pendingSinceMs=this.clock.now()}consumePasteBytes(chunk){let paste=this.paste,combined=concatBytes(paste.tail,chunk),endIndex=indexOfBytes(combined,BRACKETED_PASTE_END);if(endIndex!==-1)return this.pushPasteBytes(combined.subarray(0,endIndex)),this.events.push({type:"paste",bytes:joinPasteBytes(paste.parts,paste.totalLength)}),this.paste=null,combined.subarray(endIndex+BRACKETED_PASTE_END.length);let keep=Math.min(BRACKETED_PASTE_END.length-1,combined.length),stableLength=combined.length-keep;if(stableLength>0)this.pushPasteBytes(combined.subarray(0,stableLength));return paste.tail=Uint8Array.from(combined.subarray(stableLength)),EMPTY_BYTES}pushPasteBytes(bytes){if(bytes.length===0)return;this.paste.parts.push(Uint8Array.from(bytes)),this.paste.totalLength+=bytes.length}reconcileDeferredStateWithProtocolContext(){switch(this.state.tag){case"csi_parametric_deferred":if(!canDeferParametricCsi(this.state,this.protocolContext))this.emitOpaqueResponse("unknown",this.pending.view().subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);return;case"csi_private_reply_deferred":if(!canDeferPrivateReplyCsi(this.protocolContext))this.emitOpaqueResponse("unknown",this.pending.view().subarray(this.unitStart,this.cursor)),this.state={tag:"ground"},this.consumePrefix(this.cursor);return}}reconcileTimeoutState(){if(!this.armTimeouts)return;if(this.paste||this.pendingSinceMs===null||this.pending.length===0){this.clearTimeout();return}this.clearTimeout(),this.timeoutId=this.clock.setTimeout(()=>{if(this.timeoutId=null,this.destroyed)return;try{this.flushTimeout(this.clock.now()),this.onTimeoutFlush?.()}catch(error2){console.error("stdin parser timeout flush failed",error2)}},this.timeoutMs)}clearTimeout(){if(!this.timeoutId)return;this.clock.clearTimeout(this.timeoutId),this.timeoutId=null}resetState(){this.pending.reset(INITIAL_PENDING_CAPACITY),this.events.length=0,this.pendingSinceMs=null,this.forceFlush=!1,this.justFlushedEsc=!1,this.state={tag:"ground"},this.cursor=0,this.unitStart=0,this.paste=null,this.mouseParser.reset()}}function getSpecificity(group){return group.split(".").length}function shouldSuppressInInjection(group,meta){if(meta?.isInjection)return!1;return group==="markup.raw.block"}function treeSitterToTextChunks(content,highlights,syntaxStyle,options){let chunks=[],defaultStyle=syntaxStyle.getStyle("default"),concealEnabled=options?.enabled??!0,injectionContainerRanges=[],boundaries=[];for(let i2=0;i2<highlights.length;i2++){let[start2,end,,meta]=highlights[i2];if(start2===end)continue;if(meta?.containsInjection)injectionContainerRanges.push({start:start2,end});boundaries.push({offset:start2,type:"start",highlightIndex:i2}),boundaries.push({offset:end,type:"end",highlightIndex:i2})}boundaries.sort((a,b2)=>{if(a.offset!==b2.offset)return a.offset-b2.offset;if(a.type==="end"&&b2.type==="start")return-1;if(a.type==="start"&&b2.type==="end")return 1;return 0});let activeHighlights=new Set,currentOffset=0;for(let i2=0;i2<boundaries.length;i2++){let boundary=boundaries[i2];if(currentOffset<boundary.offset&&activeHighlights.size>0){let segmentText=content.slice(currentOffset,boundary.offset),activeGroups=[];for(let idx of activeHighlights){let[,,group,meta]=highlights[idx];activeGroups.push({group,meta,index:idx})}let concealHighlight=concealEnabled?activeGroups.find((h)=>h.meta?.conceal!==void 0||h.group==="conceal"||h.group.startsWith("conceal.")):void 0;if(concealHighlight){let replacementText="";if(concealHighlight.meta?.conceal!==void 0)replacementText=concealHighlight.meta.conceal;else if(concealHighlight.group==="conceal.with.space")replacementText=" ";if(replacementText)chunks.push({__isChunk:!0,text:replacementText,fg:defaultStyle?.fg,bg:defaultStyle?.bg,attributes:defaultStyle?createTextAttributes({bold:defaultStyle.bold,italic:defaultStyle.italic,underline:defaultStyle.underline,dim:defaultStyle.dim}):0})}else{let insideInjectionContainer=injectionContainerRanges.some((range)=>currentOffset>=range.start&&currentOffset<range.end),sortedGroups=activeGroups.filter((h)=>{if(insideInjectionContainer&&shouldSuppressInInjection(h.group,h.meta))return!1;return!0}).sort((a,b2)=>{let aSpec=getSpecificity(a.group),bSpec=getSpecificity(b2.group);if(aSpec!==bSpec)return aSpec-bSpec;return a.index-b2.index}),mergedStyle={};for(let{group}of sortedGroups){let styleForGroup=syntaxStyle.getStyle(group);if(!styleForGroup&&group.includes(".")){let baseName=group.split(".")[0];styleForGroup=syntaxStyle.getStyle(baseName)}if(styleForGroup){if(styleForGroup.fg!==void 0)mergedStyle.fg=styleForGroup.fg;if(styleForGroup.bg!==void 0)mergedStyle.bg=styleForGroup.bg;if(styleForGroup.bold!==void 0)mergedStyle.bold=styleForGroup.bold;if(styleForGroup.italic!==void 0)mergedStyle.italic=styleForGroup.italic;if(styleForGroup.underline!==void 0)mergedStyle.underline=styleForGroup.underline;if(styleForGroup.dim!==void 0)mergedStyle.dim=styleForGroup.dim}else if(group.includes(".")){let baseName=group.split(".")[0];if(env.OTUI_TS_STYLE_WARN)console.warn(`Syntax style not found for group "${group}" or base scope "${baseName}", using default style`)}else if(env.OTUI_TS_STYLE_WARN)console.warn(`Syntax style not found for group "${group}", using default style`)}let finalStyle=Object.keys(mergedStyle).length>0?mergedStyle:defaultStyle;chunks.push({__isChunk:!0,text:segmentText,fg:finalStyle?.fg,bg:finalStyle?.bg,attributes:finalStyle?createTextAttributes({bold:finalStyle.bold,italic:finalStyle.italic,underline:finalStyle.underline,dim:finalStyle.dim}):0})}}else if(currentOffset<boundary.offset){let text=content.slice(currentOffset,boundary.offset);chunks.push({__isChunk:!0,text,fg:defaultStyle?.fg,bg:defaultStyle?.bg,attributes:defaultStyle?createTextAttributes({bold:defaultStyle.bold,italic:defaultStyle.italic,underline:defaultStyle.underline,dim:defaultStyle.dim}):0})}if(boundary.type==="start")activeHighlights.add(boundary.highlightIndex);else if(activeHighlights.delete(boundary.highlightIndex),concealEnabled){let[,,group,meta]=highlights[boundary.highlightIndex];if(meta?.concealLines!==void 0){if(boundary.offset<content.length&&content[boundary.offset]===`
1637
- `){currentOffset=boundary.offset+1;continue}}if(meta?.conceal!==void 0){if(meta.conceal===" "){if(boundary.offset<content.length&&content[boundary.offset]===" "){currentOffset=boundary.offset+1;continue}}else if(meta.conceal===""&&group==="conceal"&&!meta.isInjection){if(boundary.offset<content.length&&content[boundary.offset]===" "){currentOffset=boundary.offset+1;continue}}}}currentOffset=boundary.offset}if(currentOffset<content.length){let text=content.slice(currentOffset);chunks.push({__isChunk:!0,text,fg:defaultStyle?.fg,bg:defaultStyle?.bg,attributes:defaultStyle?createTextAttributes({bold:defaultStyle.bold,italic:defaultStyle.italic,underline:defaultStyle.underline,dim:defaultStyle.dim}):0})}return chunks}async function treeSitterToStyledText(content,filetype,syntaxStyle,client,options){let result=await client.highlightOnce(content,filetype);if(result.highlights&&result.highlights.length>0){let chunks=treeSitterToTextChunks(content,result.highlights,syntaxStyle,options?.conceal);return new StyledText(chunks)}else{let defaultStyle=syntaxStyle.mergeStyles("default"),chunks=[{__isChunk:!0,text:content,fg:defaultStyle.fg,bg:defaultStyle.bg,attributes:defaultStyle.attributes}];return new StyledText(chunks)}}class DebounceController{scopeId;constructor(scopeId){if(this.scopeId=scopeId,!TIMERS_MAP.has(this.scopeId))TIMERS_MAP.set(this.scopeId,new Map)}debounce(id,ms,fn){let scopeMap=TIMERS_MAP.get(this.scopeId);return new Promise((resolve10,reject)=>{if(scopeMap.has(id))clearTimeout(scopeMap.get(id));let timerId=setTimeout(()=>{try{resolve10(fn())}catch(error2){reject(error2)}scopeMap.delete(id)},ms);scopeMap.set(id,timerId)})}clearDebounce(id){let scopeMap=TIMERS_MAP.get(this.scopeId);if(scopeMap&&scopeMap.has(id))clearTimeout(scopeMap.get(id)),scopeMap.delete(id)}clear(){let scopeMap=TIMERS_MAP.get(this.scopeId);if(scopeMap)scopeMap.forEach((timerId)=>clearTimeout(timerId)),scopeMap.clear()}}function createDebounce(scopeId){return new DebounceController(scopeId)}function clearDebounceScope(scopeId){let scopeMap=TIMERS_MAP.get(scopeId);if(scopeMap)scopeMap.forEach((timerId)=>clearTimeout(timerId)),scopeMap.clear()}class ProcessQueue{processor;queue=[];processing=!1;autoProcess=!0;constructor(processor,autoProcess=!0){this.processor=processor,this.autoProcess=autoProcess}enqueue(item){if(this.queue.push(item),!this.processing&&this.autoProcess)this.processQueue()}processQueue(){if(this.queue.length===0)return;this.processing=!0,queueMicrotask(async()=>{if(this.queue.length===0){this.processing=!1;return}let item=this.queue.shift();try{await this.processor(item)}catch(error2){console.error("Error processing queue item:",error2)}if(this.queue.length>0)this.processQueue();else this.processing=!1})}clear(){this.queue=[]}isProcessing(){return this.processing}size(){return this.queue.length}}function getParsers(){if(!_cachedParsers)_cachedParsers=[{filetype:"javascript",aliases:["javascriptreact"],queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_javascript_default)},{filetype:"typescript",aliases:["typescriptreact"],queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default2)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_typescript_default)},{filetype:"markdown",queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default3)],injections:[resolve8(dirname10(fileURLToPath2(import.meta.url)),injections_default)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_markdown_default),injectionMapping:{nodeTypes:{inline:"markdown_inline",pipe_table_cell:"markdown_inline"},infoStringMap:{javascript:"javascript",js:"javascript",jsx:"javascriptreact",javascriptreact:"javascriptreact",typescript:"typescript",ts:"typescript",tsx:"typescriptreact",typescriptreact:"typescriptreact",markdown:"markdown",md:"markdown"}}},{filetype:"markdown_inline",queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default4)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_markdown_inline_default)},{filetype:"zig",queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default5)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_zig_default)}];return _cachedParsers}function isBunfsPath(path6){return path6.includes("$bunfs")||/^B:[\\/]~BUN/i.test(path6)}function getBunfsRootPath(){return process.platform==="win32"?"B:\\~BUN\\root":"/$bunfs/root"}function normalizeBunfsPath(fileName){return join50(getBunfsRootPath(),basename8(fileName))}function addDefaultParsers(parsers2){for(let parser of parsers2)DEFAULT_PARSERS=[...DEFAULT_PARSERS.filter((existingParser)=>existingParser.filetype!==parser.filetype),parser]}function isValidDirectoryName(name){if(!name||typeof name!=="string")return!1;if(name.trim().length===0)return!1;if(["CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"].includes(name.toUpperCase()))return!1;if(/[<>:"|?*/\\\x00-\x1f]/.test(name))return!1;if(name.endsWith(".")||name.endsWith(" "))return!1;if(name==="."||name==="..")return!1;return!0}function getDataPaths(){return singleton("data-paths-opentui",()=>new DataPathsManager)}function normalizeFiletypeToken(value){return value.trim().replace(/^\./,"").toLowerCase()||void 0}function getBasename(value){let normalizedValue=value.trim().replaceAll("\\","/");if(!normalizedValue)return;return path22.posix.basename(normalizedValue).toLowerCase()||void 0}function extToFiletype(extension){let normalizedExtension=normalizeFiletypeToken(extension);if(!normalizedExtension)return;return extensionToFiletype.get(normalizedExtension)}function pathToFiletype(path32){if(typeof path32!=="string")return;let basename22=getBasename(path32);if(!basename22)return;let basenameFiletype=basenameToFiletype.get(basename22);if(basenameFiletype)return basenameFiletype;let lastDot=basename22.lastIndexOf(".");if(lastDot===-1||lastDot===basename22.length-1)return;let extension=basename22.substring(lastDot+1);return extToFiletype(extension)}function infoStringToFiletype(infoString){if(typeof infoString!=="string")return;let token=infoString.trim().split(/\s+/,1)[0],directBasenameMatch=basenameToFiletype.get(token.toLowerCase());if(directBasenameMatch)return directBasenameMatch;let normalizedToken=normalizeFiletypeToken(token);if(!normalizedToken)return;return basenameToFiletype.get(normalizedToken)??pathToFiletype(normalizedToken)??extToFiletype(normalizedToken)??normalizedToken}class DownloadUtils{static hashUrl(url){let hash=0;for(let i2=0;i2<url.length;i2++){let char=url.charCodeAt(i2);hash=(hash<<5)-hash+char,hash=hash&hash}return Math.abs(hash).toString(16)}static async downloadOrLoad(source,cacheDir,cacheSubdir,fileExtension,useHashForCache=!0,filetype){if(source.startsWith("http://")||source.startsWith("https://")){let cacheFileName;if(useHashForCache){let hash=this.hashUrl(source);cacheFileName=filetype?`${filetype}-${hash}${fileExtension}`:`${hash}${fileExtension}`}else cacheFileName=path3.basename(source);let cacheFile=path3.join(cacheDir,cacheSubdir,cacheFileName);await mkdir9(path3.dirname(cacheFile),{recursive:!0});try{let cachedContent=await readFile13(cacheFile);if(cachedContent.byteLength>0)return console.log(`Loaded from cache: ${cacheFile} (${source})`),{content:cachedContent,filePath:cacheFile}}catch(error2){}try{console.log(`Downloading from URL: ${source}`);let response=await fetch(source);if(!response.ok)return{error:`Failed to fetch from ${source}: ${response.statusText}`};let content=Buffer.from(await response.arrayBuffer());try{await writeFile6(cacheFile,Buffer.from(content)),console.log(`Cached: ${source}`)}catch(cacheError){console.warn(`Failed to cache: ${cacheError}`)}return{content,filePath:cacheFile}}catch(error2){return{error:`Error downloading from ${source}: ${error2}`}}}else try{return console.log(`Loading from local path: ${source}`),{content:await readFile13(source),filePath:source}}catch(error2){return{error:`Error loading from local path ${source}: ${error2}`}}}static async downloadToPath(source,targetPath){let isUrl2=source.startsWith("http://")||source.startsWith("https://");if(await mkdir9(path3.dirname(targetPath),{recursive:!0}),isUrl2)try{console.log(`Downloading from URL: ${source}`);let response=await fetch(source);if(!response.ok)return{error:`Failed to fetch from ${source}: ${response.statusText}`};let content=Buffer.from(await response.arrayBuffer());return await writeFile6(targetPath,Buffer.from(content)),console.log(`Downloaded: ${source} -> ${targetPath}`),{content,filePath:targetPath}}catch(error2){return{error:`Error downloading from ${source}: ${error2}`}}else try{console.log(`Copying from local path: ${source}`);let content=await readFile13(source);return await writeFile6(targetPath,Buffer.from(content)),{content,filePath:targetPath}}catch(error2){return{error:`Error copying from local path ${source}: ${error2}`}}}static async fetchHighlightQueries(sources,cacheDir,filetype){let queryPromises=sources.map((source)=>this.fetchHighlightQuery(source,cacheDir,filetype));return(await Promise.all(queryPromises)).filter((query)=>query.trim().length>0).join(`
1637
+ `){currentOffset=boundary.offset+1;continue}}if(meta?.conceal!==void 0){if(meta.conceal===" "){if(boundary.offset<content.length&&content[boundary.offset]===" "){currentOffset=boundary.offset+1;continue}}else if(meta.conceal===""&&group==="conceal"&&!meta.isInjection){if(boundary.offset<content.length&&content[boundary.offset]===" "){currentOffset=boundary.offset+1;continue}}}}currentOffset=boundary.offset}if(currentOffset<content.length){let text=content.slice(currentOffset);chunks.push({__isChunk:!0,text,fg:defaultStyle?.fg,bg:defaultStyle?.bg,attributes:defaultStyle?createTextAttributes({bold:defaultStyle.bold,italic:defaultStyle.italic,underline:defaultStyle.underline,dim:defaultStyle.dim}):0})}return chunks}async function treeSitterToStyledText(content,filetype,syntaxStyle,client,options){let result=await client.highlightOnce(content,filetype);if(result.highlights&&result.highlights.length>0){let chunks=treeSitterToTextChunks(content,result.highlights,syntaxStyle,options?.conceal);return new StyledText(chunks)}else{let defaultStyle=syntaxStyle.mergeStyles("default"),chunks=[{__isChunk:!0,text:content,fg:defaultStyle.fg,bg:defaultStyle.bg,attributes:defaultStyle.attributes}];return new StyledText(chunks)}}class DebounceController{scopeId;constructor(scopeId){if(this.scopeId=scopeId,!TIMERS_MAP.has(this.scopeId))TIMERS_MAP.set(this.scopeId,new Map)}debounce(id,ms,fn){let scopeMap=TIMERS_MAP.get(this.scopeId);return new Promise((resolve10,reject)=>{if(scopeMap.has(id))clearTimeout(scopeMap.get(id));let timerId=setTimeout(()=>{try{resolve10(fn())}catch(error2){reject(error2)}scopeMap.delete(id)},ms);scopeMap.set(id,timerId)})}clearDebounce(id){let scopeMap=TIMERS_MAP.get(this.scopeId);if(scopeMap&&scopeMap.has(id))clearTimeout(scopeMap.get(id)),scopeMap.delete(id)}clear(){let scopeMap=TIMERS_MAP.get(this.scopeId);if(scopeMap)scopeMap.forEach((timerId)=>clearTimeout(timerId)),scopeMap.clear()}}function createDebounce(scopeId){return new DebounceController(scopeId)}function clearDebounceScope(scopeId){let scopeMap=TIMERS_MAP.get(scopeId);if(scopeMap)scopeMap.forEach((timerId)=>clearTimeout(timerId)),scopeMap.clear()}class ProcessQueue{processor;queue=[];processing=!1;autoProcess=!0;constructor(processor,autoProcess=!0){this.processor=processor,this.autoProcess=autoProcess}enqueue(item){if(this.queue.push(item),!this.processing&&this.autoProcess)this.processQueue()}processQueue(){if(this.queue.length===0)return;this.processing=!0,queueMicrotask(async()=>{if(this.queue.length===0){this.processing=!1;return}let item=this.queue.shift();try{await this.processor(item)}catch(error2){console.error("Error processing queue item:",error2)}if(this.queue.length>0)this.processQueue();else this.processing=!1})}clear(){this.queue=[]}isProcessing(){return this.processing}size(){return this.queue.length}}function getParsers(){if(!_cachedParsers)_cachedParsers=[{filetype:"javascript",aliases:["javascriptreact"],queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_javascript_default)},{filetype:"typescript",aliases:["typescriptreact"],queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default2)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_typescript_default)},{filetype:"markdown",queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default3)],injections:[resolve8(dirname10(fileURLToPath2(import.meta.url)),injections_default)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_markdown_default),injectionMapping:{nodeTypes:{inline:"markdown_inline",pipe_table_cell:"markdown_inline"},infoStringMap:{javascript:"javascript",js:"javascript",jsx:"javascriptreact",javascriptreact:"javascriptreact",typescript:"typescript",ts:"typescript",tsx:"typescriptreact",typescriptreact:"typescriptreact",markdown:"markdown",md:"markdown"}}},{filetype:"markdown_inline",queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default4)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_markdown_inline_default)},{filetype:"zig",queries:{highlights:[resolve8(dirname10(fileURLToPath2(import.meta.url)),highlights_default5)]},wasm:resolve8(dirname10(fileURLToPath2(import.meta.url)),tree_sitter_zig_default)}];return _cachedParsers}function isBunfsPath(path6){return path6.includes("$bunfs")||/^B:[\\/]~BUN/i.test(path6)}function getBunfsRootPath(){return process.platform==="win32"?"B:\\~BUN\\root":"/$bunfs/root"}function normalizeBunfsPath(fileName){return join50(getBunfsRootPath(),basename9(fileName))}function addDefaultParsers(parsers2){for(let parser of parsers2)DEFAULT_PARSERS=[...DEFAULT_PARSERS.filter((existingParser)=>existingParser.filetype!==parser.filetype),parser]}function isValidDirectoryName(name){if(!name||typeof name!=="string")return!1;if(name.trim().length===0)return!1;if(["CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"].includes(name.toUpperCase()))return!1;if(/[<>:"|?*/\\\x00-\x1f]/.test(name))return!1;if(name.endsWith(".")||name.endsWith(" "))return!1;if(name==="."||name==="..")return!1;return!0}function getDataPaths(){return singleton("data-paths-opentui",()=>new DataPathsManager)}function normalizeFiletypeToken(value){return value.trim().replace(/^\./,"").toLowerCase()||void 0}function getBasename(value){let normalizedValue=value.trim().replaceAll("\\","/");if(!normalizedValue)return;return path22.posix.basename(normalizedValue).toLowerCase()||void 0}function extToFiletype(extension){let normalizedExtension=normalizeFiletypeToken(extension);if(!normalizedExtension)return;return extensionToFiletype.get(normalizedExtension)}function pathToFiletype(path32){if(typeof path32!=="string")return;let basename22=getBasename(path32);if(!basename22)return;let basenameFiletype=basenameToFiletype.get(basename22);if(basenameFiletype)return basenameFiletype;let lastDot=basename22.lastIndexOf(".");if(lastDot===-1||lastDot===basename22.length-1)return;let extension=basename22.substring(lastDot+1);return extToFiletype(extension)}function infoStringToFiletype(infoString){if(typeof infoString!=="string")return;let token=infoString.trim().split(/\s+/,1)[0],directBasenameMatch=basenameToFiletype.get(token.toLowerCase());if(directBasenameMatch)return directBasenameMatch;let normalizedToken=normalizeFiletypeToken(token);if(!normalizedToken)return;return basenameToFiletype.get(normalizedToken)??pathToFiletype(normalizedToken)??extToFiletype(normalizedToken)??normalizedToken}class DownloadUtils{static hashUrl(url){let hash=0;for(let i2=0;i2<url.length;i2++){let char=url.charCodeAt(i2);hash=(hash<<5)-hash+char,hash=hash&hash}return Math.abs(hash).toString(16)}static async downloadOrLoad(source,cacheDir,cacheSubdir,fileExtension,useHashForCache=!0,filetype){if(source.startsWith("http://")||source.startsWith("https://")){let cacheFileName;if(useHashForCache){let hash=this.hashUrl(source);cacheFileName=filetype?`${filetype}-${hash}${fileExtension}`:`${hash}${fileExtension}`}else cacheFileName=path3.basename(source);let cacheFile=path3.join(cacheDir,cacheSubdir,cacheFileName);await mkdir9(path3.dirname(cacheFile),{recursive:!0});try{let cachedContent=await readFile13(cacheFile);if(cachedContent.byteLength>0)return console.log(`Loaded from cache: ${cacheFile} (${source})`),{content:cachedContent,filePath:cacheFile}}catch(error2){}try{console.log(`Downloading from URL: ${source}`);let response=await fetch(source);if(!response.ok)return{error:`Failed to fetch from ${source}: ${response.statusText}`};let content=Buffer.from(await response.arrayBuffer());try{await writeFile6(cacheFile,Buffer.from(content)),console.log(`Cached: ${source}`)}catch(cacheError){console.warn(`Failed to cache: ${cacheError}`)}return{content,filePath:cacheFile}}catch(error2){return{error:`Error downloading from ${source}: ${error2}`}}}else try{return console.log(`Loading from local path: ${source}`),{content:await readFile13(source),filePath:source}}catch(error2){return{error:`Error loading from local path ${source}: ${error2}`}}}static async downloadToPath(source,targetPath){let isUrl2=source.startsWith("http://")||source.startsWith("https://");if(await mkdir9(path3.dirname(targetPath),{recursive:!0}),isUrl2)try{console.log(`Downloading from URL: ${source}`);let response=await fetch(source);if(!response.ok)return{error:`Failed to fetch from ${source}: ${response.statusText}`};let content=Buffer.from(await response.arrayBuffer());return await writeFile6(targetPath,Buffer.from(content)),console.log(`Downloaded: ${source} -> ${targetPath}`),{content,filePath:targetPath}}catch(error2){return{error:`Error downloading from ${source}: ${error2}`}}else try{console.log(`Copying from local path: ${source}`);let content=await readFile13(source);return await writeFile6(targetPath,Buffer.from(content)),{content,filePath:targetPath}}catch(error2){return{error:`Error copying from local path ${source}: ${error2}`}}}static async fetchHighlightQueries(sources,cacheDir,filetype){let queryPromises=sources.map((source)=>this.fetchHighlightQuery(source,cacheDir,filetype));return(await Promise.all(queryPromises)).filter((query)=>query.trim().length>0).join(`
1638
1638
  `)}static async fetchHighlightQuery(source,cacheDir,filetype){let result=await this.downloadOrLoad(source,cacheDir,"queries",".scm",!0,filetype);if(result.error)return console.error(`Error fetching highlight query from ${source}:`,result.error),"";if(result.content)return new TextDecoder().decode(result.content);return""}}function getDefaultOptions(){return{configPath:path4.resolve(__dirname2,"../parsers-config"),assetsDir:path4.resolve(__dirname2),outputPath:path4.resolve(__dirname2,"../default-parsers.ts")}}async function loadConfig2(configPath2){let ext=path4.extname(configPath2),resolvedConfigPath=configPath2;if(ext===""){let file=(await readdir7(path4.dirname(configPath2))).find((file2)=>file2.startsWith(path4.basename(configPath2))&&(file2.endsWith(".json")||file2.endsWith(".ts")||file2.endsWith(".js")));if(!file)throw Error(`No config file found for ${configPath2}`);resolvedConfigPath=path4.join(path4.dirname(configPath2),file),ext=path4.extname(resolvedConfigPath)}if(ext===".json"){let configContent=await readFile22(resolvedConfigPath,"utf-8");return JSON.parse(configContent)}else if(ext===".ts"||ext===".js"){let{default:configContent}=await import(resolvedConfigPath);return configContent}throw Error(`Unsupported config file extension: ${ext}`)}async function downloadLanguage(filetype,languageUrl,assetsDir,outputPath){let languageDir=path4.join(assetsDir,filetype),languageFilename=path4.basename(languageUrl),languagePath=path4.join(languageDir,languageFilename),result=await DownloadUtils.downloadToPath(languageUrl,languagePath);if(result.error)throw Error(`Failed to download language for ${filetype}: ${result.error}`);return"./"+path4.relative(path4.dirname(outputPath),languagePath)}async function downloadAndCombineQueries(filetype,queryUrls,assetsDir,outputPath,queryType,configPath2){let queriesDir=path4.join(assetsDir,filetype),queryPath=path4.join(queriesDir,`${queryType}.scm`),queryContents=[];for(let i2=0;i2<queryUrls.length;i2++){let queryUrl=queryUrls[i2];if(queryUrl.startsWith("./")){console.log(` Using local query ${i2+1}/${queryUrls.length}: ${queryUrl}`);try{let localPath=path4.resolve(path4.dirname(configPath2),queryUrl),content=await readFile22(localPath,"utf-8");if(content.trim())queryContents.push(content),console.log(` \u2713 Loaded ${content.split(`
1639
1639
  `).length} lines from local file`)}catch(error2){console.warn(`Failed to read local query from ${queryUrl}: ${error2}`);continue}}else{console.log(` Downloading query ${i2+1}/${queryUrls.length}: ${queryUrl}`);try{let response=await fetch(queryUrl);if(!response.ok){console.warn(`Failed to download query from ${queryUrl}: ${response.statusText}`);continue}let content=await response.text();if(content.trim())queryContents.push(`; Query from: ${queryUrl}
1640
1640
  ${content}`),console.log(` \u2713 Downloaded ${content.split(`
@@ -2264,9 +2264,9 @@ Run: genie send '<SHIP|FIX-FIRST|BLOCKED> \u2014 <summary>' --to team-lead`;awai
2264
2264
  [${time}] ASSISTANT:`,truncate3(entry.text,500)];case"tool_result":return[`
2265
2265
  [${time}] RESULT:`,` ${truncate3(entry.text,500)}`];case"system":return[`
2266
2266
  [${time}] SYSTEM:`,entry.text];default:return[]}}function formatFullConversation(entries){return entries.flatMap(formatTranscriptEntryForDisplay).join(`
2267
- `)}async function findWorker(identifier){let worker=await get(identifier);if(worker)return worker;if(worker=await findByTask(identifier),worker)return worker;return(await list()).find((w)=>w.id.includes(identifier)||w.taskId?.includes(identifier)||w.taskTitle?.toLowerCase().includes(identifier.toLowerCase()))??null}async function resolveContext(workerIdOrName,options){if(options.logFile)return{worker:{id:"direct",paneId:"",session:"",worktree:null,startedAt:new Date().toISOString(),state:"idle",lastStateChange:new Date().toISOString(),repoPath:process.cwd(),provider:"claude"},workerId:"direct",provider:"claude",duration:"N/A"};let worker=await findWorker(workerIdOrName);if(!worker)console.error(`Agent "${workerIdOrName}" not found. Run \`genie agent list\` to see agents.`),process.exit(1);let elapsed=getElapsedTime(worker);return{worker,workerId:worker.id,provider:worker.provider??"claude",branch:worker.worktree?`work/${worker.taskId}`:void 0,duration:elapsed.formatted}}function buildFilter(options){let filter={},hasFilter=!1;if(options.last&&options.last>0)filter.last=options.last,hasFilter=!0;if(options.after)filter.since=options.after,hasFilter=!0;if(options.type)filter.roles=[options.type],hasFilter=!0;return hasFilter?filter:void 0}function filterSinceExchanges(entries,since){let userCount=0;for(let i2=entries.length-1;i2>=0;i2--)if(entries[i2].role==="user"){if(userCount++,userCount>=since)return entries.slice(i2)}return entries}async function loadEntries(ctx,options){let{readTranscript:readTranscript2,getProvider:getProvider3}=await Promise.resolve().then(() => exports_transcript);if(options.logFile)return(await getProvider3(ctx.worker)).readEntries(options.logFile);return readTranscript2(ctx.worker)}function filterEntries(entries,options){let{applyFilter:applyFilter2}=__toCommonJS(exports_transcript),filtered=options.since&&options.since>0?filterSinceExchanges(entries,options.since):entries,transcriptFilter=buildFilter(options);if(transcriptFilter)filtered=applyFilter2(filtered,transcriptFilter);return filtered}function outputEntries(filtered,options){if(options.ndjson){for(let entry of filtered){let{raw:_raw,...rest}=entry;console.log(JSON.stringify(options.raw?entry:rest))}return!0}if(options.raw){for(let entry of filtered)console.log(JSON.stringify(entry.raw));return!0}if(options.full)return console.log(formatFullConversation(filtered)),!0;return!1}async function historyCommand(workerIdOrName,options){let ctx=await resolveContext(workerIdOrName,options),entries=await loadEntries(ctx,options);if(entries.length===0)console.error(`No transcript found for agent "${ctx.workerId}".`),process.exit(1);let filtered=filterEntries(entries,options);if(outputEntries(filtered,options))return;let events=extractEvents(filtered),toolCallCount=entries.filter((e)=>e.role==="tool_call").length,userMessageCount=entries.filter((e)=>e.role==="user").length,stats={workerId:ctx.workerId,taskId:ctx.workerId,branch:ctx.branch,provider:ctx.provider,duration:ctx.duration,totalEntries:entries.length,compressedLines:events.length,compressionRatio:entries.length/Math.max(events.length,1),exchanges:userMessageCount,toolCalls:toolCallCount,status:detectStatus(entries)};if(options.json){console.log(JSON.stringify({stats,events},null,2));return}console.log(formatEventsForDisplay(events,stats))}init_export_format();import{readFileSync as readFileSync16}from"fs";var IMPORT_LEVELS=[["schedules","sessions","projects","agent_templates","agent_checkpoints","tags","task_types","notification_preferences","app_store","os_config","golden_images","warm_pool","instances"],["triggers","boards","board_templates","agents","conversations","installed_apps","app_versions"],["tasks","runs","messages","conversation_members","mailbox","team_chat"],["task_tags","task_actors","task_dependencies","task_stage_log","heartbeats","machine_snapshots"]],SELF_REFERENTIAL_COLUMNS={tasks:"parent_id",messages:"reply_to_id",conversations:"parent_message_id"};function getTableLevel(table){for(let i2=0;i2<IMPORT_LEVELS.length;i2++)if(IMPORT_LEVELS[i2].includes(table))return i2;return-1}function sortByImportOrder(tables){return[...tables].sort((a,b2)=>{let la=getTableLevel(a),lb=getTableLevel(b2);return(la===-1?999:la)-(lb===-1?999:lb)})}function getPrimaryKey(table){return{task_tags:["task_id","tag_id"],task_actors:["task_id","actor_type","actor_id","role"],task_dependencies:["task_id","depends_on_id"],conversation_members:["conversation_id","actor_type","actor_id"],notification_preferences:["actor_type","actor_id","channel"]}[table]??["id"]}async function getSql2(){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return getConnection2()}async function getActorName2(){let{getActor:getActor2}=await Promise.resolve().then(() => (init_audit(),exports_audit));return getActor2()}async function detectTables2(sql,tables){let{filterAvailableTables:filterAvailableTables2}=await Promise.resolve().then(() => exports_table_detect);return filterAvailableTables2(sql,tables)}async function detectConflicts(sql,table,rows){if(rows.length===0)return[];let pk=getPrimaryKey(table);if(pk.length===1){let key=pk[0],ids=rows.map((r)=>r[key]),existing=await sql.unsafe(`SELECT ${key} FROM ${table} WHERE ${key} = ANY($1)`,[ids]),existingSet=new Set(existing.map((r)=>String(r[key])));return rows.filter((r)=>existingSet.has(String(r[key])))}let conflicts=[];for(let row of rows){let conditions=pk.map((col,i2)=>`${col} = $${i2+1}`).join(" AND "),values2=pk.map((col)=>row[col]);if((await sql.unsafe(`SELECT 1 FROM ${table} WHERE ${conditions} LIMIT 1`,values2)).length>0)conflicts.push(row)}return conflicts}function prepareRow(row,table,selfRefUpdates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],entries=Object.entries(row),columns=entries.map(([k])=>k),values2=entries.map(([,v])=>v);if(selfRefCol&&row[selfRefCol]!=null){let idx=columns.indexOf(selfRefCol);if(idx!==-1){let originalSelfRef=values2[idx];values2[idx]=null;let pk=getPrimaryKey(table);selfRefUpdates.push({pk:pk.length===1?row[pk[0]]:pk.map((k)=>row[k]),value:originalSelfRef})}}return{columns,values:values2,quotedCols:columns.map((c)=>`"${c}"`).join(", "),placeholders:values2.map((_,i2)=>`$${i2+1}`).join(", ")}}async function insertOneRow(tx,table,row,prepared,mode){let{quotedCols,placeholders,values:values2}=prepared,pk=getPrimaryKey(table);if(mode==="overwrite"){let pkCondition=pk.map((col,i2)=>`"${col}" = $${values2.length+i2+1}`).join(" AND "),pkValues=pk.map((col)=>row[col]);await tx.unsafe(`DELETE FROM ${table} WHERE ${pkCondition}`,pkValues),await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}else if(mode==="merge"){let onConflict=pk.map((c)=>`"${c}"`).join(", ");await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders}) ON CONFLICT (${onConflict}) DO NOTHING`,values2)}else await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}async function updateSelfRefs(tx,table,updates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],pk=getPrimaryKey(table);if(pk.length!==1)return;for(let{pk:pkVal,value}of updates)await tx.unsafe(`UPDATE ${table} SET "${selfRefCol}" = $1 WHERE "${pk[0]}" = $2`,[value,pkVal])}async function insertRows(tx,table,rows,mode){if(rows.length===0)return 0;let selfRefUpdates=[];for(let row of rows){let prepared=prepareRow(row,table,selfRefUpdates);await insertOneRow(tx,table,row,prepared,mode)}if(selfRefUpdates.length>0)await updateSelfRefs(tx,table,selfRefUpdates);return rows.length}function parseExportFile(filePath){let raw=readFileSync16(filePath,"utf-8"),parsed;try{parsed=JSON.parse(raw)}catch{throw Error(`Invalid JSON in ${filePath}`)}let validation=validateExportDocument(parsed);if(!validation.valid)throw Error(`Invalid export document: ${validation.error}`);return validation.doc}async function filterTablesByGroup(allTables,groupFilter){if(!groupFilter||groupFilter.length===0)return allTables;let{GROUP_TABLES:GROUP_TABLES2}=await Promise.resolve().then(() => (init_export_format(),exports_export_format)),allowedTables=new Set;for(let group of groupFilter){let tables=GROUP_TABLES2[group];if(tables)for(let t of tables)allowedTables.add(t);else console.warn(`Warning: Unknown group "${group}", skipping`)}return allTables.filter((t)=>allowedTables.has(t))}async function checkConflicts(sql,tables,data){for(let table of tables){let rows=data[table];if(!rows||rows.length===0)continue;let conflicts=await detectConflicts(sql,table,rows);if(conflicts.length>0){let pk=getPrimaryKey(table),ids=conflicts.slice(0,5).map((r)=>pk.map((k)=>r[k]).join(",")).join("; ");throw Error(`Conflict in table "${table}": ${conflicts.length} existing row(s) (e.g., ${ids}). Use --merge or --overwrite to resolve.`)}}}async function runImport(filePath,mode,groupFilter){let doc=parseExportFile(filePath),tablesToImport=await filterTablesByGroup(Object.keys(doc.data),groupFilter);if(tablesToImport.length===0){console.log("No tables to import.");return}tablesToImport=sortByImportOrder(tablesToImport);let sql=await getSql2(),{available}=await detectTables2(sql,tablesToImport),skippedTables=tablesToImport.filter((t)=>!available.includes(t));if(tablesToImport=available,skippedTables.length>0)console.log(`Skipping tables not in database: ${skippedTables.join(", ")}`);if(mode==="fail")await checkConflicts(sql,tablesToImport,doc.data);let totalInserted=0,tableStats={};await sql.begin(async(tx)=>{for(let table of tablesToImport){let rows=doc.data[table];if(!rows||rows.length===0)continue;let count=await insertRows(tx,table,rows,mode);tableStats[table]=count,totalInserted+=count}});let actor=await getActorName2(),{recordAuditEvent:recordAuditEvent2}=await Promise.resolve().then(() => (init_audit(),exports_audit));await recordAuditEvent2("import",filePath,"import_complete",actor,{mode,tables:tableStats,totalRows:totalInserted,skippedTables,sourceVersion:doc.version,sourceDate:doc.exportedAt}),console.log(`Import complete: ${totalInserted} rows across ${Object.keys(tableStats).length} tables`);for(let[table,count]of Object.entries(tableStats))if(count>0)console.log(` ${table}: ${count} rows`);if(skippedTables.length>0)console.log(`Skipped (not in DB): ${skippedTables.join(", ")}`)}function registerImportCommands(program2){program2.command("import <file>").description("Import genie data from JSON export").option("--fail","Abort on any conflict (default)").option("--merge","Skip existing rows, import new ones").option("--overwrite","Replace existing rows with imported data").option("--groups <list>","Comma-separated groups to import (e.g., boards,tags)").action(async(file,options)=>{try{let mode="fail";if(options.overwrite)mode="overwrite";else if(options.merge)mode="merge";let groupFilter=options.groups?.split(",").map((g)=>g.trim());await runImport(file,mode,groupFilter)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_workspace();init_templates();import{existsSync as existsSync33,mkdirSync as mkdirSync14,symlinkSync,writeFileSync as writeFileSync14}from"fs";import{basename as basename5,join as join40}from"path";function detectPgUrl(){if(process.env.DATABASE_URL)return process.env.DATABASE_URL;if(process.env.PG_URL)return process.env.PG_URL;try{let{execSync:execSync12}=__require("child_process"),match=execSync12("pgrep -af pgserve 2>/dev/null",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).match(/postgres(?:ql)?:\/\/[^\s]+/);if(match)return match[0]}catch{}return}async function initWorkspace2(){let cwd=process.cwd(),existing=findWorkspace(cwd);if(existing){console.log(`Already inside workspace: ${existing.root}`);return}let genieDir=join40(cwd,".genie");mkdirSync14(genieDir,{recursive:!0});let pgUrl=detectPgUrl(),config={name:basename5(cwd),pgUrl,tmuxSocket:"genie"};if(writeFileSync14(join40(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
2267
+ `)}async function findWorker(identifier){let worker=await get(identifier);if(worker)return worker;if(worker=await findByTask(identifier),worker)return worker;return(await list()).find((w)=>w.id.includes(identifier)||w.taskId?.includes(identifier)||w.taskTitle?.toLowerCase().includes(identifier.toLowerCase()))??null}async function resolveContext(workerIdOrName,options){if(options.logFile)return{worker:{id:"direct",paneId:"",session:"",worktree:null,startedAt:new Date().toISOString(),state:"idle",lastStateChange:new Date().toISOString(),repoPath:process.cwd(),provider:"claude"},workerId:"direct",provider:"claude",duration:"N/A"};let worker=await findWorker(workerIdOrName);if(!worker)console.error(`Agent "${workerIdOrName}" not found. Run \`genie agent list\` to see agents.`),process.exit(1);let elapsed=getElapsedTime(worker);return{worker,workerId:worker.id,provider:worker.provider??"claude",branch:worker.worktree?`work/${worker.taskId}`:void 0,duration:elapsed.formatted}}function buildFilter(options){let filter={},hasFilter=!1;if(options.last&&options.last>0)filter.last=options.last,hasFilter=!0;if(options.after)filter.since=options.after,hasFilter=!0;if(options.type)filter.roles=[options.type],hasFilter=!0;return hasFilter?filter:void 0}function filterSinceExchanges(entries,since){let userCount=0;for(let i2=entries.length-1;i2>=0;i2--)if(entries[i2].role==="user"){if(userCount++,userCount>=since)return entries.slice(i2)}return entries}async function loadEntries(ctx,options){let{readTranscript:readTranscript2,getProvider:getProvider3}=await Promise.resolve().then(() => exports_transcript);if(options.logFile)return(await getProvider3(ctx.worker)).readEntries(options.logFile);return readTranscript2(ctx.worker)}function filterEntries(entries,options){let{applyFilter:applyFilter2}=__toCommonJS(exports_transcript),filtered=options.since&&options.since>0?filterSinceExchanges(entries,options.since):entries,transcriptFilter=buildFilter(options);if(transcriptFilter)filtered=applyFilter2(filtered,transcriptFilter);return filtered}function outputEntries(filtered,options){if(options.ndjson){for(let entry of filtered){let{raw:_raw,...rest}=entry;console.log(JSON.stringify(options.raw?entry:rest))}return!0}if(options.raw){for(let entry of filtered)console.log(JSON.stringify(entry.raw));return!0}if(options.full)return console.log(formatFullConversation(filtered)),!0;return!1}async function historyCommand(workerIdOrName,options){let ctx=await resolveContext(workerIdOrName,options),entries=await loadEntries(ctx,options);if(entries.length===0)console.error(`No transcript found for agent "${ctx.workerId}".`),process.exit(1);let filtered=filterEntries(entries,options);if(outputEntries(filtered,options))return;let events=extractEvents(filtered),toolCallCount=entries.filter((e)=>e.role==="tool_call").length,userMessageCount=entries.filter((e)=>e.role==="user").length,stats={workerId:ctx.workerId,taskId:ctx.workerId,branch:ctx.branch,provider:ctx.provider,duration:ctx.duration,totalEntries:entries.length,compressedLines:events.length,compressionRatio:entries.length/Math.max(events.length,1),exchanges:userMessageCount,toolCalls:toolCallCount,status:detectStatus(entries)};if(options.json){console.log(JSON.stringify({stats,events},null,2));return}console.log(formatEventsForDisplay(events,stats))}init_export_format();import{readFileSync as readFileSync16}from"fs";var IMPORT_LEVELS=[["schedules","sessions","projects","agent_templates","agent_checkpoints","tags","task_types","notification_preferences","app_store","os_config","golden_images","warm_pool","instances"],["triggers","boards","board_templates","agents","conversations","installed_apps","app_versions"],["tasks","runs","messages","conversation_members","mailbox","team_chat"],["task_tags","task_actors","task_dependencies","task_stage_log","heartbeats","machine_snapshots"]],SELF_REFERENTIAL_COLUMNS={tasks:"parent_id",messages:"reply_to_id",conversations:"parent_message_id"};function getTableLevel(table){for(let i2=0;i2<IMPORT_LEVELS.length;i2++)if(IMPORT_LEVELS[i2].includes(table))return i2;return-1}function sortByImportOrder(tables){return[...tables].sort((a,b2)=>{let la=getTableLevel(a),lb=getTableLevel(b2);return(la===-1?999:la)-(lb===-1?999:lb)})}function getPrimaryKey(table){return{task_tags:["task_id","tag_id"],task_actors:["task_id","actor_type","actor_id","role"],task_dependencies:["task_id","depends_on_id"],conversation_members:["conversation_id","actor_type","actor_id"],notification_preferences:["actor_type","actor_id","channel"]}[table]??["id"]}async function getSql2(){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return getConnection2()}async function getActorName2(){let{getActor:getActor2}=await Promise.resolve().then(() => (init_audit(),exports_audit));return getActor2()}async function detectTables2(sql,tables){let{filterAvailableTables:filterAvailableTables2}=await Promise.resolve().then(() => exports_table_detect);return filterAvailableTables2(sql,tables)}async function detectConflicts(sql,table,rows){if(rows.length===0)return[];let pk=getPrimaryKey(table);if(pk.length===1){let key=pk[0],ids=rows.map((r)=>r[key]),existing=await sql.unsafe(`SELECT ${key} FROM ${table} WHERE ${key} = ANY($1)`,[ids]),existingSet=new Set(existing.map((r)=>String(r[key])));return rows.filter((r)=>existingSet.has(String(r[key])))}let conflicts=[];for(let row of rows){let conditions=pk.map((col,i2)=>`${col} = $${i2+1}`).join(" AND "),values2=pk.map((col)=>row[col]);if((await sql.unsafe(`SELECT 1 FROM ${table} WHERE ${conditions} LIMIT 1`,values2)).length>0)conflicts.push(row)}return conflicts}function prepareRow(row,table,selfRefUpdates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],entries=Object.entries(row),columns=entries.map(([k])=>k),values2=entries.map(([,v])=>v);if(selfRefCol&&row[selfRefCol]!=null){let idx=columns.indexOf(selfRefCol);if(idx!==-1){let originalSelfRef=values2[idx];values2[idx]=null;let pk=getPrimaryKey(table);selfRefUpdates.push({pk:pk.length===1?row[pk[0]]:pk.map((k)=>row[k]),value:originalSelfRef})}}return{columns,values:values2,quotedCols:columns.map((c)=>`"${c}"`).join(", "),placeholders:values2.map((_,i2)=>`$${i2+1}`).join(", ")}}async function insertOneRow(tx,table,row,prepared,mode){let{quotedCols,placeholders,values:values2}=prepared,pk=getPrimaryKey(table);if(mode==="overwrite"){let pkCondition=pk.map((col,i2)=>`"${col}" = $${values2.length+i2+1}`).join(" AND "),pkValues=pk.map((col)=>row[col]);await tx.unsafe(`DELETE FROM ${table} WHERE ${pkCondition}`,pkValues),await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}else if(mode==="merge"){let onConflict=pk.map((c)=>`"${c}"`).join(", ");await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders}) ON CONFLICT (${onConflict}) DO NOTHING`,values2)}else await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}async function updateSelfRefs(tx,table,updates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],pk=getPrimaryKey(table);if(pk.length!==1)return;for(let{pk:pkVal,value}of updates)await tx.unsafe(`UPDATE ${table} SET "${selfRefCol}" = $1 WHERE "${pk[0]}" = $2`,[value,pkVal])}async function insertRows(tx,table,rows,mode){if(rows.length===0)return 0;let selfRefUpdates=[];for(let row of rows){let prepared=prepareRow(row,table,selfRefUpdates);await insertOneRow(tx,table,row,prepared,mode)}if(selfRefUpdates.length>0)await updateSelfRefs(tx,table,selfRefUpdates);return rows.length}function parseExportFile(filePath){let raw=readFileSync16(filePath,"utf-8"),parsed;try{parsed=JSON.parse(raw)}catch{throw Error(`Invalid JSON in ${filePath}`)}let validation=validateExportDocument(parsed);if(!validation.valid)throw Error(`Invalid export document: ${validation.error}`);return validation.doc}async function filterTablesByGroup(allTables,groupFilter){if(!groupFilter||groupFilter.length===0)return allTables;let{GROUP_TABLES:GROUP_TABLES2}=await Promise.resolve().then(() => (init_export_format(),exports_export_format)),allowedTables=new Set;for(let group of groupFilter){let tables=GROUP_TABLES2[group];if(tables)for(let t of tables)allowedTables.add(t);else console.warn(`Warning: Unknown group "${group}", skipping`)}return allTables.filter((t)=>allowedTables.has(t))}async function checkConflicts(sql,tables,data){for(let table of tables){let rows=data[table];if(!rows||rows.length===0)continue;let conflicts=await detectConflicts(sql,table,rows);if(conflicts.length>0){let pk=getPrimaryKey(table),ids=conflicts.slice(0,5).map((r)=>pk.map((k)=>r[k]).join(",")).join("; ");throw Error(`Conflict in table "${table}": ${conflicts.length} existing row(s) (e.g., ${ids}). Use --merge or --overwrite to resolve.`)}}}async function runImport(filePath,mode,groupFilter){let doc=parseExportFile(filePath),tablesToImport=await filterTablesByGroup(Object.keys(doc.data),groupFilter);if(tablesToImport.length===0){console.log("No tables to import.");return}tablesToImport=sortByImportOrder(tablesToImport);let sql=await getSql2(),{available}=await detectTables2(sql,tablesToImport),skippedTables=tablesToImport.filter((t)=>!available.includes(t));if(tablesToImport=available,skippedTables.length>0)console.log(`Skipping tables not in database: ${skippedTables.join(", ")}`);if(mode==="fail")await checkConflicts(sql,tablesToImport,doc.data);let totalInserted=0,tableStats={};await sql.begin(async(tx)=>{for(let table of tablesToImport){let rows=doc.data[table];if(!rows||rows.length===0)continue;let count=await insertRows(tx,table,rows,mode);tableStats[table]=count,totalInserted+=count}});let actor=await getActorName2(),{recordAuditEvent:recordAuditEvent2}=await Promise.resolve().then(() => (init_audit(),exports_audit));await recordAuditEvent2("import",filePath,"import_complete",actor,{mode,tables:tableStats,totalRows:totalInserted,skippedTables,sourceVersion:doc.version,sourceDate:doc.exportedAt}),console.log(`Import complete: ${totalInserted} rows across ${Object.keys(tableStats).length} tables`);for(let[table,count]of Object.entries(tableStats))if(count>0)console.log(` ${table}: ${count} rows`);if(skippedTables.length>0)console.log(`Skipped (not in DB): ${skippedTables.join(", ")}`)}function registerImportCommands(program2){program2.command("import <file>").description("Import genie data from JSON export").option("--fail","Abort on any conflict (default)").option("--merge","Skip existing rows, import new ones").option("--overwrite","Replace existing rows with imported data").option("--groups <list>","Comma-separated groups to import (e.g., boards,tags)").action(async(file,options)=>{try{let mode="fail";if(options.overwrite)mode="overwrite";else if(options.merge)mode="merge";let groupFilter=options.groups?.split(",").map((g)=>g.trim());await runImport(file,mode,groupFilter)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_workspace();init_templates();import{existsSync as existsSync33,mkdirSync as mkdirSync14,symlinkSync,writeFileSync as writeFileSync14}from"fs";import{basename as basename6,join as join40}from"path";function detectPgUrl(){if(process.env.DATABASE_URL)return process.env.DATABASE_URL;if(process.env.PG_URL)return process.env.PG_URL;try{let{execSync:execSync12}=__require("child_process"),match=execSync12("pgrep -af pgserve 2>/dev/null",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).match(/postgres(?:ql)?:\/\/[^\s]+/);if(match)return match[0]}catch{}return}async function initWorkspace2(){let cwd=process.cwd(),existing=findWorkspace(cwd);if(existing){console.log(`Already inside workspace: ${existing.root}`);return}let genieDir=join40(cwd,".genie");mkdirSync14(genieDir,{recursive:!0});let pgUrl=detectPgUrl(),config={name:basename6(cwd),pgUrl,tmuxSocket:"genie"};if(writeFileSync14(join40(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
2268
2268
  `),console.log(`Workspace created: ${cwd}`),pgUrl)console.log(` pgUrl: ${pgUrl}`);let agents=scanAgents2(cwd);if(agents.length>0){console.log(` Found ${agents.length} agent(s): ${agents.join(", ")}`);try{let{syncAgentDirectory:syncAgentDirectory2}=await Promise.resolve().then(() => (init_agent_sync(),exports_agent_sync)),result=await syncAgentDirectory2(cwd);if(result.registered.length>0)console.log(` Registered: ${result.registered.join(", ")}`);if(result.updated.length>0)console.log(` Updated: ${result.updated.join(", ")}`)}catch{}}}async function initAgent(name){let cwd=process.cwd(),ws=findWorkspace(cwd);if(!ws)console.error("Error: Not in a genie workspace. Run `genie init` first."),process.exit(1);let agentDir=join40(ws.root,"agents",name);if(existsSync33(agentDir))console.error(`Error: Agent directory already exists: ${agentDir}`),process.exit(1);mkdirSync14(agentDir,{recursive:!0}),mkdirSync14(join40(agentDir,"brain","memory"),{recursive:!0}),mkdirSync14(join40(agentDir,".claude"),{recursive:!0}),scaffoldAgentFiles(agentDir,name),writeFileSync14(join40(agentDir,".claude","settings.local.json"),`${JSON.stringify({agentName:name},null,2)}
2269
- `);let reposTarget=join40(ws.root,"repos");if(existsSync33(reposTarget))try{symlinkSync(reposTarget,join40(agentDir,"repos"))}catch{}if(console.log(`Agent scaffolded: agents/${name}/`),console.log(" AGENTS.md, SOUL.md, HEARTBEAT.md"),console.log(" brain/memory/"),console.log(" .claude/settings.local.json"),existsSync33(join40(agentDir,"repos")))console.log(" repos -> ../repos (symlink)")}function registerInitCommands(program2){program2.command("init").description("Initialize a genie workspace").action(async()=>{await initWorkspace2()}).command("agent <name>").description("Scaffold a new agent in the workspace").action(async(name)=>{await initAgent(name)})}init_agent_cache();init_audit();init_db();import{execSync as execSync12}from"child_process";import{existsSync as existsSync35,mkdirSync as mkdirSync15,rmSync as rmSync3}from"fs";import{homedir as homedir25}from"os";import{basename as basename7,join as join42}from"path";init_js_yaml();import{existsSync as existsSync34,readFileSync as readFileSync17}from"fs";import{basename as basename6,join as join41}from"path";var ITEM_TYPES=["agent","skill","app","board","workflow","stack","template","hook"];function parseManifest(yamlContent){let raw=load2(yamlContent);if(!raw||typeof raw!=="object")throw Error("Manifest YAML is empty or not an object");let obj=raw;if(!obj.name||typeof obj.name!=="string")throw Error("Manifest is missing required field: name");if(!obj.type||typeof obj.type!=="string")throw Error("Manifest is missing required field: type");if(!obj.version||typeof obj.version!=="string")throw Error("Manifest is missing required field: version");if(!ITEM_TYPES.includes(obj.type))throw Error(`Invalid item type "${obj.type}". Must be one of: ${ITEM_TYPES.join(", ")}`);return obj}var VALID_GATES=new Set(["human","agent","human+agent"]);function validateManifest(manifest,itemDir){let errors3=[],warnings=[];if(!manifest.name)errors3.push("Missing required field: name");if(!manifest.type)errors3.push("Missing required field: type");if(!manifest.version)errors3.push("Missing required field: version");if(manifest.type&&!ITEM_TYPES.includes(manifest.type))errors3.push(`Invalid item type "${manifest.type}". Must be one of: ${ITEM_TYPES.join(", ")}`);let{type:type2}=manifest;if(type2&&!manifest[type2])warnings.push(`Manifest type is "${type2}" but no "${type2}" section is defined`);if(manifest.agent)validateEntrypoint(manifest.agent.entrypoint,itemDir,"agent",errors3);if(manifest.skill)validateEntrypoint(manifest.skill.entrypoint,itemDir,"skill",errors3);if(manifest.app)validateEntrypoint(manifest.app.entrypoint,itemDir,"app",errors3);if(manifest.board)validateStages(manifest.board.stages,errors3);if(manifest.workflow)validateCron(manifest.workflow.cron,errors3);if(manifest.stack)validateStackItems(manifest.stack.items,errors3);return{valid:errors3.length===0,errors:errors3,warnings}}function validateEntrypoint(entrypoint,itemDir,section,errors3){if(!entrypoint){errors3.push(`${section} section is missing required field: entrypoint`);return}let fullPath=join41(itemDir,entrypoint);if(!existsSync34(fullPath))errors3.push(`${section} entrypoint not found: ${entrypoint} (expected at ${fullPath})`)}function validateStages(stages,errors3){if(!stages||!Array.isArray(stages)){errors3.push("board section is missing required field: stages");return}for(let i2=0;i2<stages.length;i2++){let stage=stages[i2];if(!stage.name)errors3.push(`board.stages[${i2}] is missing required field: name`);if(!stage.gate)errors3.push(`board.stages[${i2}] is missing required field: gate`);else if(!VALID_GATES.has(stage.gate))errors3.push(`board.stages[${i2}].gate "${stage.gate}" is invalid. Must be one of: human, agent, human+agent`)}}function validateCron(cron,errors3){if(!cron){errors3.push("workflow section is missing required field: cron");return}let fields=cron.trim().split(/\s+/);if(fields.length<5||fields.length>6)errors3.push(`workflow.cron "${cron}" is invalid: expected 5 or 6 space-separated fields, got ${fields.length}`)}function validateStackItems(items,errors3){if(!items||!Array.isArray(items)){errors3.push("stack section is missing required field: items");return}for(let i2=0;i2<items.length;i2++){let item=items[i2];if(!item.type)errors3.push(`stack.items[${i2}] is missing required field: type`);if(!item.source&&!item.inline)errors3.push(`stack.items[${i2}] must have either "source" or "inline: true"`)}}async function detectManifest(dir){let yamlPath=join41(dir,"genie.yaml");if(existsSync34(yamlPath))try{let content=readFileSync17(yamlPath,"utf-8");return{manifest:parseManifest(content),source:"genie.yaml"}}catch(err){return{error:`Failed to parse genie.yaml: ${err.message}`}}let dirName=basename6(dir),agentsPath=join41(dir,"AGENTS.md");if(existsSync34(agentsPath))return{manifest:inferAgentManifest(agentsPath,dirName),source:"AGENTS.md"};let manifestTsPath=join41(dir,"manifest.ts");if(existsSync34(manifestTsPath))return{manifest:{name:dirName,type:"app",version:"0.0.0"},source:"manifest.ts"};let skillPath=join41(dir,"skill.md");if(existsSync34(skillPath))return{manifest:{name:dirName,type:"skill",version:"0.0.0"},source:"skill.md"};return{error:"No manifest found. Create a genie.yaml or use a recognized file pattern (AGENTS.md, manifest.ts, skill.md)."}}function extractFrontmatter(filePath){let match=readFileSync17(filePath,"utf-8").match(/^---\s*\n([\s\S]*?)\n---/);if(!match)return null;try{let parsed=load2(match[1]);if(parsed&&typeof parsed==="object")return parsed}catch{}return null}function inferAgentManifest(agentsPath,dirName){let frontmatter=extractFrontmatter(agentsPath),name=frontmatter?.name||dirName,model=frontmatter?.model,roles=Array.isArray(frontmatter?.roles)?frontmatter.roles:void 0,manifest={name,type:"agent",version:"0.0.0"};if(model||roles)manifest.agent={entrypoint:"AGENTS.md",...model&&{model},...roles&&{roles}};return manifest}var GENIE_HOME4=process.env.GENIE_HOME??join42(homedir25(),".genie"),ITEMS_DIR=join42(GENIE_HOME4,"items");function parseInstallTarget(target){let url=target,version,atIdx=url.lastIndexOf("@");if(atIdx>0&&!url.slice(atIdx).includes("/"))version=url.slice(atIdx+1),url=url.slice(0,atIdx);if(!url.startsWith("http")&&!url.startsWith("git@")&&!url.startsWith("ssh://"))url=`https://${url}`;if(url.startsWith("https://")&&!url.endsWith(".git"))url=`${url}.git`;let name=basename7(url,".git");return{url,version,name}}function cloneRepo(url,dest,options){let args=["git","clone"];if(options.shallow!==!1)args.push("--depth","1");if(options.version)args.push("--branch",options.version);args.push(url,dest),execSync12(args.join(" "),{stdio:"pipe",timeout:120000})}function cleanupDir(dir){if(existsSync35(dir))rmSync3(dir,{recursive:!0,force:!0})}async function registerByType(manifest,installPath){switch(manifest.type){case"agent":await regenerateAgentCache();break;case"board":await registerBoard(manifest);break;case"workflow":await registerWorkflow(manifest);break;case"stack":await installStack(manifest,installPath);break}}async function registerBoard(manifest){if(!manifest.board?.stages)return;if(!await isAvailable())return;let sql=await getConnection(),stages=manifest.board.stages.map((s,i2)=>({id:crypto.randomUUID(),name:s.name,label:s.label??s.name,gate:s.gate,action:s.action??null,auto_advance:s.auto_advance??!1,roles:s.roles??["*"],color:s.color??"#94a3b8",parallel:!1,on_fail:null,position:i2,transitions:[]}));await sql`
2269
+ `);let reposTarget=join40(ws.root,"repos");if(existsSync33(reposTarget))try{symlinkSync(reposTarget,join40(agentDir,"repos"))}catch{}if(console.log(`Agent scaffolded: agents/${name}/`),console.log(" AGENTS.md, SOUL.md, HEARTBEAT.md"),console.log(" brain/memory/"),console.log(" .claude/settings.local.json"),existsSync33(join40(agentDir,"repos")))console.log(" repos -> ../repos (symlink)")}function registerInitCommands(program2){program2.command("init").description("Initialize a genie workspace").action(async()=>{await initWorkspace2()}).command("agent <name>").description("Scaffold a new agent in the workspace").action(async(name)=>{await initAgent(name)})}init_agent_cache();init_audit();init_db();import{execSync as execSync12}from"child_process";import{existsSync as existsSync35,mkdirSync as mkdirSync15,rmSync as rmSync3}from"fs";import{homedir as homedir25}from"os";import{basename as basename8,join as join42}from"path";init_js_yaml();import{existsSync as existsSync34,readFileSync as readFileSync17}from"fs";import{basename as basename7,join as join41}from"path";var ITEM_TYPES=["agent","skill","app","board","workflow","stack","template","hook"];function parseManifest(yamlContent){let raw=load2(yamlContent);if(!raw||typeof raw!=="object")throw Error("Manifest YAML is empty or not an object");let obj=raw;if(!obj.name||typeof obj.name!=="string")throw Error("Manifest is missing required field: name");if(!obj.type||typeof obj.type!=="string")throw Error("Manifest is missing required field: type");if(!obj.version||typeof obj.version!=="string")throw Error("Manifest is missing required field: version");if(!ITEM_TYPES.includes(obj.type))throw Error(`Invalid item type "${obj.type}". Must be one of: ${ITEM_TYPES.join(", ")}`);return obj}var VALID_GATES=new Set(["human","agent","human+agent"]);function validateManifest(manifest,itemDir){let errors3=[],warnings=[];if(!manifest.name)errors3.push("Missing required field: name");if(!manifest.type)errors3.push("Missing required field: type");if(!manifest.version)errors3.push("Missing required field: version");if(manifest.type&&!ITEM_TYPES.includes(manifest.type))errors3.push(`Invalid item type "${manifest.type}". Must be one of: ${ITEM_TYPES.join(", ")}`);let{type:type2}=manifest;if(type2&&!manifest[type2])warnings.push(`Manifest type is "${type2}" but no "${type2}" section is defined`);if(manifest.agent)validateEntrypoint(manifest.agent.entrypoint,itemDir,"agent",errors3);if(manifest.skill)validateEntrypoint(manifest.skill.entrypoint,itemDir,"skill",errors3);if(manifest.app)validateEntrypoint(manifest.app.entrypoint,itemDir,"app",errors3);if(manifest.board)validateStages(manifest.board.stages,errors3);if(manifest.workflow)validateCron(manifest.workflow.cron,errors3);if(manifest.stack)validateStackItems(manifest.stack.items,errors3);return{valid:errors3.length===0,errors:errors3,warnings}}function validateEntrypoint(entrypoint,itemDir,section,errors3){if(!entrypoint){errors3.push(`${section} section is missing required field: entrypoint`);return}let fullPath=join41(itemDir,entrypoint);if(!existsSync34(fullPath))errors3.push(`${section} entrypoint not found: ${entrypoint} (expected at ${fullPath})`)}function validateStages(stages,errors3){if(!stages||!Array.isArray(stages)){errors3.push("board section is missing required field: stages");return}for(let i2=0;i2<stages.length;i2++){let stage=stages[i2];if(!stage.name)errors3.push(`board.stages[${i2}] is missing required field: name`);if(!stage.gate)errors3.push(`board.stages[${i2}] is missing required field: gate`);else if(!VALID_GATES.has(stage.gate))errors3.push(`board.stages[${i2}].gate "${stage.gate}" is invalid. Must be one of: human, agent, human+agent`)}}function validateCron(cron,errors3){if(!cron){errors3.push("workflow section is missing required field: cron");return}let fields=cron.trim().split(/\s+/);if(fields.length<5||fields.length>6)errors3.push(`workflow.cron "${cron}" is invalid: expected 5 or 6 space-separated fields, got ${fields.length}`)}function validateStackItems(items,errors3){if(!items||!Array.isArray(items)){errors3.push("stack section is missing required field: items");return}for(let i2=0;i2<items.length;i2++){let item=items[i2];if(!item.type)errors3.push(`stack.items[${i2}] is missing required field: type`);if(!item.source&&!item.inline)errors3.push(`stack.items[${i2}] must have either "source" or "inline: true"`)}}async function detectManifest(dir){let yamlPath=join41(dir,"genie.yaml");if(existsSync34(yamlPath))try{let content=readFileSync17(yamlPath,"utf-8");return{manifest:parseManifest(content),source:"genie.yaml"}}catch(err){return{error:`Failed to parse genie.yaml: ${err.message}`}}let dirName=basename7(dir),agentsPath=join41(dir,"AGENTS.md");if(existsSync34(agentsPath))return{manifest:inferAgentManifest(agentsPath,dirName),source:"AGENTS.md"};let manifestTsPath=join41(dir,"manifest.ts");if(existsSync34(manifestTsPath))return{manifest:{name:dirName,type:"app",version:"0.0.0"},source:"manifest.ts"};let skillPath=join41(dir,"skill.md");if(existsSync34(skillPath))return{manifest:{name:dirName,type:"skill",version:"0.0.0"},source:"skill.md"};return{error:"No manifest found. Create a genie.yaml or use a recognized file pattern (AGENTS.md, manifest.ts, skill.md)."}}function extractFrontmatter(filePath){let match=readFileSync17(filePath,"utf-8").match(/^---\s*\n([\s\S]*?)\n---/);if(!match)return null;try{let parsed=load2(match[1]);if(parsed&&typeof parsed==="object")return parsed}catch{}return null}function inferAgentManifest(agentsPath,dirName){let frontmatter=extractFrontmatter(agentsPath),name=frontmatter?.name||dirName,model=frontmatter?.model,roles=Array.isArray(frontmatter?.roles)?frontmatter.roles:void 0,manifest={name,type:"agent",version:"0.0.0"};if(model||roles)manifest.agent={entrypoint:"AGENTS.md",...model&&{model},...roles&&{roles}};return manifest}var GENIE_HOME4=process.env.GENIE_HOME??join42(homedir25(),".genie"),ITEMS_DIR=join42(GENIE_HOME4,"items");function parseInstallTarget(target){let url=target,version,atIdx=url.lastIndexOf("@");if(atIdx>0&&!url.slice(atIdx).includes("/"))version=url.slice(atIdx+1),url=url.slice(0,atIdx);if(!url.startsWith("http")&&!url.startsWith("git@")&&!url.startsWith("ssh://"))url=`https://${url}`;if(url.startsWith("https://")&&!url.endsWith(".git"))url=`${url}.git`;let name=basename8(url,".git");return{url,version,name}}function cloneRepo(url,dest,options){let args=["git","clone"];if(options.shallow!==!1)args.push("--depth","1");if(options.version)args.push("--branch",options.version);args.push(url,dest),execSync12(args.join(" "),{stdio:"pipe",timeout:120000})}function cleanupDir(dir){if(existsSync35(dir))rmSync3(dir,{recursive:!0,force:!0})}async function registerByType(manifest,installPath){switch(manifest.type){case"agent":await regenerateAgentCache();break;case"board":await registerBoard(manifest);break;case"workflow":await registerWorkflow(manifest);break;case"stack":await installStack(manifest,installPath);break}}async function registerBoard(manifest){if(!manifest.board?.stages)return;if(!await isAvailable())return;let sql=await getConnection(),stages=manifest.board.stages.map((s,i2)=>({id:crypto.randomUUID(),name:s.name,label:s.label??s.name,gate:s.gate,action:s.action??null,auto_advance:s.auto_advance??!1,roles:s.roles??["*"],color:s.color??"#94a3b8",parallel:!1,on_fail:null,position:i2,transitions:[]}));await sql`
2270
2270
  INSERT INTO task_types (id, name, description, stages, is_builtin)
2271
2271
  VALUES (
2272
2272
  ${manifest.name},
@@ -2626,7 +2626,8 @@ Valid columns for board "${board.name}": ${validCols}`),process.exit(1)}catch{}}
2626
2626
  Messages:`);for(let msg of messages2){let time=formatTimestamp(msg.createdAt),reply=msg.replyToId?` (reply to #${msg.replyToId})`:"";console.log(` [${time}] ${msg.senderId}: ${msg.body}${reply}`)}}}async function printTaskDetail(task){printTaskFields(task),await printTaskRelations(task),await printTaskMessages(task),console.log("")}function printColumnTasks(label,colTasks,useColor=!0){if(console.log(`
2627
2627
  \u2500\u2500 ${label} (${colTasks.length} task${colTasks.length===1?"":"s"}) \u2500\u2500`),colTasks.length===0){console.log(" (empty)");return}for(let t of colTasks){let pc=useColor?PRIORITY_COLORS[t.priority]??"":"",reset2=useColor?RESET2:"";console.log(` ${pc}#${t.seq}${reset2} ${padRight(truncate(t.title,35),37)} ${padRight(t.status,14)} ${t.priority}`)}}async function printByColumn(tasks,boardName){let board=await(await getBoardService2()).getBoard(boardName);if(!board)console.error(`Error: Board not found: ${boardName}`),process.exit(1);console.log(`
2628
2628
  Board: ${board.name} (${board.id})`),console.log("\u2550".repeat(40));let columns=[...board.columns].sort((a,b2)=>a.position-b2.position);for(let col of columns)printColumnTasks(col.label,tasks.filter((t)=>t.columnId===col.id));let columnIds=new Set(columns.map((c)=>c.id)),orphaned=tasks.filter((t)=>t.columnId&&!columnIds.has(t.columnId));if(orphaned.length>0)printColumnTasks("Orphaned",orphaned,!1);console.log("")}function parseGhRef(gh){let match=gh.match(/^([^#]+)#(\d+)$/);if(!match)console.error(`Error: Invalid --gh format. Expected owner/repo#N, got: ${gh}`),process.exit(1);let[,ownerRepo,num]=match;return{externalId:`${ownerRepo}#${num}`,externalUrl:`https://github.com/${ownerRepo}/issues/${num}`}}async function handleTaskCreate(title,options){let ts3=await getTaskService7(),actor=currentActor2(),repoPath,projectId;if(options.project){let project=await ts3.getProjectByName(options.project);if(!project)project=await ts3.createProject({name:options.project});projectId=project.id,repoPath=project.repoPath??void 0}let parentId;if(options.parent){if(parentId=await ts3.resolveTaskId(options.parent,repoPath)??void 0,!parentId)console.error(`Error: Parent task not found: ${options.parent}`),process.exit(1)}let boardId=await resolveBoardOption(options.board),externalId=options.externalId,externalUrl=options.externalUrl;if(options.gh){let parsed=parseGhRef(options.gh);externalId=parsed.externalId,externalUrl=parsed.externalUrl}let task=await ts3.createTask({title,typeId:options.type,priority:options.priority,dueDate:options.due,startDate:options.start,parentId,description:options.description,estimatedEffort:options.effort,boardId,externalId,externalUrl},repoPath,projectId);if(await ts3.assignTask(task.id,actor,"creator",{},task.repoPath),options.assign)await ts3.assignTask(task.id,localActor2(options.assign),"assignee",{},task.repoPath);if(options.tags){let tagIds=options.tags.split(",").map((t)=>t.trim());await ts3.tagTask(task.id,tagIds,actor,task.repoPath)}if(options.comment)await ts3.commentOnTask(task.id,actor,options.comment,task.repoPath);if(console.log(`Created task #${task.seq}: ${task.title}`),console.log(` ID: ${task.id}`),console.log(` Stage: ${task.stage} | Priority: ${task.priority}`),options.due)console.log(` Due: ${options.due}`)}async function handleCloseMerged(options){let result=await(await getCloseMergedService()).closeMergedTasks({since:options.since,dryRun:options.dryRun,repo:options.repo});if(options.dryRun)console.log("[dry-run] Would close:");for(let d of result.details){let prefix=options.dryRun?" [dry-run]":" \u2713";console.log(`${prefix} #${d.taskSeq} "${d.taskTitle}" \u2190 PR #${d.prNumber} (${d.slug})`)}let mode=options.dryRun?"[dry-run] ":"";console.log(`
2629
- ${mode}Closed ${result.closed} task${result.closed===1?"":"s"} from ${result.prsScanned} merged PR${result.prsScanned===1?"":"s"} (${result.alreadyShipped} already shipped)`)}function registerTaskCommands(program2){let task=program2.command("task").description("Task lifecycle management");task.command("create <title>").description("Create a new task").option("--type <type>","Task type","software").option("--priority <priority>","Priority: urgent, high, normal, low","normal").option("--due <date>","Due date (YYYY-MM-DD)").option("--start <date>","Start date (YYYY-MM-DD)").option("--tags <tags>","Comma-separated tag IDs").option("--parent <id>","Parent task ID or #seq").option("--assign <name>","Assign to local actor").option("--description <text>","Task description").option("--effort <effort>",'Estimated effort (e.g., "2h", "3 points")').option("--comment <msg>","Initial comment on the task").option("--project <name>","Create task in a specific project (overrides CWD)").option("--board <name>","Board name to assign task to").option("--gh <owner/repo#N>","Link to GitHub issue (sets external_id + external_url)").option("--external-id <id>","External tracker ID (e.g., JIRA-123)").option("--external-url <url>","External tracker URL").action(async(title,options)=>{try{await handleTaskCreate(title,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}});async function handleTaskList(options){let ts3=await getTaskService7(),filters={stage:options.stage,typeId:options.type,status:options.status,priority:options.priority,releaseId:options.release,dueBefore:options.dueBefore,projectName:options.project,boardName:options.board,externalId:options.gh?parseGhRef(options.gh).externalId:void 0,allProjects:options.all,includeArchived:options.all,limit:Number(options.limit)||100,offset:Number(options.offset)||0,...options.all?{limit:1e4}:{}},tasks;if(options.mine)tasks=await ts3.listTasksForActor(currentActor2(),filters);else tasks=await ts3.listTasks(filters);if(options.byColumn){if(!options.board)console.error("Error: --by-column requires --board"),process.exit(1);if(!options.includeDone)tasks=tasks.filter((t)=>t.status!=="done");await printByColumn(tasks,options.board);return}if(options.json){console.log(JSON.stringify(tasks,null,2));return}printTaskList(tasks,options.all)}task.command("list").description("List tasks with filters").option("--stage <stage>","Filter by stage").option("--type <type>","Filter by type").option("--status <status>","Filter by status").option("--priority <priority>","Filter by priority").option("--release <release>","Filter by release").option("--due-before <date>","Filter by due date").option("--mine","Show only tasks assigned to me").option("--project <name>","Show tasks for a specific project").option("--board <name>","Filter by board name").option("--gh <owner/repo#N>","Filter by GitHub issue link").option("--by-column","Group tasks by board column (kanban view)").option("--include-done","Include done tasks in kanban view (hidden by default)").option("--all","Show tasks from ALL projects").option("--limit <n>","Max number of tasks to return","100").option("--offset <n>","Skip first N tasks (for pagination)","0").option("--json","Output as JSON").action(async(options)=>{try{await handleTaskList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("show <id>").description("Show task detail (accepts task-id or #seq)").option("--json","Output as JSON").action(async(id,options)=>{try{let t=await(await getTaskService7()).getTask(id);if(!t)console.error(`Error: Task not found: ${id}`),process.exit(1);if(options.json){console.log(JSON.stringify(t,null,2));return}await printTaskDetail(t)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("link <id>").description("Link task to an external tracker (GitHub, Jira, etc.)").option("--gh <owner/repo#N>","Link to GitHub issue").option("--external-id <id>","External tracker ID").option("--external-url <url>","External tracker URL").action(async(id,options)=>{try{let ts3=await getTaskService7(),externalId,externalUrl;if(options.gh){let parsed=parseGhRef(options.gh);externalId=parsed.externalId,externalUrl=parsed.externalUrl}else if(options.externalId&&options.externalUrl)externalId=options.externalId,externalUrl=options.externalUrl;else console.error("Error: Provide --gh or both --external-id and --external-url."),process.exit(1);let t=await ts3.linkTask(id,externalId,externalUrl);if(!t)console.error(`Error: Task not found: ${id}`),process.exit(1);if(console.log(`Linked task #${t.seq} to ${externalId}`),t.externalUrl)console.log(` URL: ${t.externalUrl}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("move <id>").description("Move task to a new stage").requiredOption("--to <stage>","Target stage").option("--comment <msg>","Comment on the move").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.moveTask(id,options.to,actor,options.comment);console.log(`Moved task #${t.seq} to stage "${t.stage}".`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);if(message.includes("Invalid stage"))await handleInvalidStageError(id,message);console.error(`Error: ${message}`),process.exit(1)}}),task.command("assign <id>").description("Assign an actor to a task").requiredOption("--to <name>","Actor name").option("--role <role>","Actor role","assignee").option("--comment <msg>","Comment on the assignment").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2();if(await ts3.assignTask(id,localActor2(options.to),options.role,{}),options.comment)await ts3.commentOnTask(id,actor,options.comment);console.log(`Assigned "${options.to}" as ${options.role??"assignee"} on task ${id}.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("tag <id> <tags...>").description("Add tags to a task").action(async(id,tags)=>{try{await(await getTaskService7()).tagTask(id,tags,currentActor2()),console.log(`Tagged task ${id} with: ${tags.join(", ")}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("comment <id> <message>").description("Add a comment to a task").option("--reply-to <msgId>","Reply to a specific message ID").action(async(id,message,options)=>{try{let ts3=await getTaskService7(),replyTo=options.replyTo?Number(options.replyTo):void 0,msg=await ts3.commentOnTask(id,currentActor2(),message,void 0,replyTo);console.log(`Comment #${msg.id} added to task ${id}.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("block <id>").description("Mark task as blocked").requiredOption("--reason <reason>","Reason for blocking").option("--comment <msg>","Additional comment").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.blockTask(id,options.reason,actor,options.comment);console.log(`Task #${t.seq} blocked: ${options.reason}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("unblock <id>").description("Unblock a task").option("--comment <msg>","Comment on unblock").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.unblockTask(id,actor,options.comment);console.log(`Task #${t.seq} unblocked.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("done <id>").description("Mark task as done").option("--comment <msg>","Comment on completion").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.markDone(id,actor,options.comment);console.log(`Task #${t.seq} marked as done.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("checkout <id>").description("Atomically claim a task for execution").action(async(id)=>{try{let ts3=await getTaskService7(),runId=getRunId(),t=await ts3.checkoutTask(id,runId);console.log(`Checked out task #${t.seq} for run: ${runId}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("release <id>").description("Release task checkout claim").action(async(id)=>{try{let ts3=await getTaskService7(),runId=getRunId(),t=await ts3.releaseTask(id,runId);console.log(`Released task #${t.seq} from run: ${runId}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("unlock <id>").description("Force-release a stale checkout (admin override)").action(async(id)=>{try{let t=await(await getTaskService7()).forceUnlockTask(id);console.log(`Force-unlocked task #${t.seq}.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("close-merged").description("Auto-close tasks whose wish slugs match recently merged PRs").option("--since <duration>",'Time window for merged PRs (e.g., "24h", "7d")',"24h").option("--dry-run","Show what would be closed without acting").option("--repo <owner/repo>","Override GitHub remote detection").action(async(options)=>{try{await handleCloseMerged(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("archive <id>").description("Archive a task (soft-delete \u2014 preserves all data)").action(async(id)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.archiveTask(id,actor);console.log(`Archived task #${t.seq}: ${t.title}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("unarchive <id>").description("Restore an archived task to its previous status").action(async(id)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.unarchiveTask(id,actor);console.log(`Unarchived task #${t.seq}: ${t.title} (status: ${t.status})`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("dep <id>").description("Manage task dependencies").option("--depends-on <id2>","This task depends on id2").option("--blocks <id2>","This task blocks id2").option("--relates-to <id2>","This task relates to id2").option("--remove <id2>","Remove dependency on id2").action(async(id,options)=>{try{let ts3=await getTaskService7();if(options.remove){if(await ts3.removeDependency(id,options.remove))console.log(`Removed dependency between ${id} and ${options.remove}.`);else console.log("No dependency found to remove.");return}if(options.dependsOn)await ts3.addDependency(id,options.dependsOn,"depends_on"),console.log(`${id} now depends on ${options.dependsOn}.`);if(options.blocks)await ts3.addDependency(id,options.blocks,"blocks"),console.log(`${id} now blocks ${options.blocks}.`);if(options.relatesTo)await ts3.addDependency(id,options.relatesTo,"relates_to"),console.log(`${id} now relates to ${options.relatesTo}.`);if(!options.dependsOn&&!options.blocks&&!options.relatesTo)console.error("Error: Specify --depends-on, --blocks, --relates-to, or --remove."),process.exit(1)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_team_manager();import{existsSync as existsSync38}from"fs";import{copyFile as copyFile2,cp as cp2,mkdir as mkdir8}from"fs/promises";import{join as join49,resolve as resolve7}from"path";function registerTeamNamespace(program2){let team=program2.command("team").description("Team lifecycle management");team.command("create <name>").description("Create a new team with a git worktree").requiredOption("--repo <path>","Path to the git repository").option("--branch <branch>","Base branch to create from","dev").option("--wish <slug>","Wish slug \u2014 auto-spawns a task leader with wish context").option("--session <name>","Tmux session name (avoids session explosion on parallel creates)").option("--no-spawn","Create team and copy wish without spawning the leader (useful for testing)").action(async(name,options)=>{try{await handleTeamCreate(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("hire <agent>").description('Add an agent to a team ("council" hires all 10 council members)').option("--team <name>","Team name (auto-detects from leader context if omitted)").action(async(agent,options)=>{try{let teamName=options.team??await autoDetectTeam();if(!teamName)console.error("Error: Could not detect team. Use --team <name> to specify."),process.exit(1);let added=await hireAgent(teamName,agent);if(added.length===0)console.log(`Agent "${agent}" is already a member of "${teamName}".`);else if(agent==="council"){console.log(`Hired ${added.length} council members to "${teamName}":`);for(let name of added)console.log(` + ${name}`)}else console.log(`Hired "${agent}" to team "${teamName}".`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("fire <agent>").description("Remove an agent from a team").option("--team <name>","Team name (auto-detects from leader context if omitted)").action(async(agent,options)=>{try{let teamName=options.team??await autoDetectTeam();if(!teamName)console.error("Error: Could not detect team. Use --team <name> to specify."),process.exit(1);if(await fireAgent(teamName,agent))console.log(`Fired "${agent}" from team "${teamName}".`);else console.error(`Agent "${agent}" is not a member of "${teamName}".`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("ls [name]").alias("list").description("List teams or members of a team").option("--all","Include archived teams").option("--json","Output as JSON").action(async(name,options)=>{try{if(name)await printMembers(name,options.json);else await printTeams(options.json,options.all)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("archive <name>").description("Archive a team (preserves all data, kills members)").action(async(name)=>{try{if(await archiveTeam(name))console.log(`Team "${name}" archived.`);else console.error(`Team "${name}" not found.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("unarchive <name>").description("Restore an archived team").action(async(name)=>{try{if(await unarchiveTeam(name))console.log(`Team "${name}" unarchived.`);else console.error(`Team "${name}" not found.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("disband <name>").description("Disband a team (archives \u2014 preserves data). Use `genie team archive` directly.").action(async(name)=>{try{if(await disbandTeam(name))console.log("Note: disband now archives the team. Use `genie team archive` directly."),console.log(`Team "${name}" disbanded (archived).`);else console.error(`Team "${name}" not found.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("done <name>").description("Mark a team as done and kill all members").action(async(name)=>{try{await setTeamStatus(name,"done"),await killTeamMembers(name),console.log(`Team "${name}" marked as done. All members killed.`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("blocked <name>").description("Mark a team as blocked and kill all members").action(async(name)=>{try{await setTeamStatus(name,"blocked"),await killTeamMembers(name),console.log(`Team "${name}" marked as blocked. All members killed.`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}async function handleTeamCreate(name,options){if(options.wish){let resolvedRepo=resolve7(options.repo),wishPath=join49(resolvedRepo,".genie","wishes",options.wish,"WISH.md");if(!existsSync38(wishPath)){let cwdWishDir=join49(process.cwd(),".genie","wishes",options.wish),cwdWishPath=join49(cwdWishDir,"WISH.md");if(existsSync38(cwdWishPath)){let destDir=join49(resolvedRepo,".genie","wishes",options.wish);await mkdir8(destDir,{recursive:!0}),await cp2(cwdWishDir,destDir,{recursive:!0}),console.log(`Wish: copied ${options.wish}/WISH.md to repo`)}else console.error(`Error: Wish not found at ${wishPath}`),process.exit(1)}}let config=await createTeam(name,options.repo,options.branch),needsUpdate=!1;if(options.wish)config.wishSlug=options.wish,needsUpdate=!0;if(options.session)config.tmuxSessionName=options.session,needsUpdate=!0;if(needsUpdate)await updateTeamConfig(name,config);if(console.log(`Team "${config.name}" created.`),console.log(` Worktree: ${config.worktreePath}`),console.log(` Branch: ${config.name} (from ${config.baseBranch})`),config.tmuxSessionName)console.log(` Session: ${config.tmuxSessionName}`);if(config.nativeTeamsEnabled)console.log(" Native teams: enabled");if(options.wish&&options.spawn!==!1)await spawnLeaderWithWish(config,options.wish,options.repo,options.session)}async function spawnLeaderWithWish(config,slug,repoPath,sessionOverride){let{handleWorkerSpawn:handleWorkerSpawn2}=await Promise.resolve().then(() => (init_agents(),exports_agents)),{findSessionByRepo:findSessionByRepo2}=await Promise.resolve().then(() => (init_agent_directory(),exports_agent_directory)),resolvedRepo=resolve7(repoPath),tmuxSession=sessionOverride??await findSessionByRepo2(resolvedRepo)??config.name;config.tmuxSessionName=tmuxSession,await updateTeamConfig(config.name,config);let sourceWishPath=join49(resolvedRepo,".genie","wishes",slug,"WISH.md");if(!existsSync38(sourceWishPath))console.error(`Error: Wish not found at ${sourceWishPath}`),process.exit(1);let destWishDir=join49(config.worktreePath,".genie","wishes",slug);await mkdir8(destWishDir,{recursive:!0});let destWishPath=join49(destWishDir,"WISH.md");await copyFile2(sourceWishPath,destWishPath),console.log(` Wish: copied ${slug}/WISH.md into worktree`);let standardTeam=["team-lead","engineer","reviewer","qa","fix"];for(let role of standardTeam)await hireAgent(config.name,role);console.log(` Team: hired ${standardTeam.join(", ")}`);let members=standardTeam.filter((r)=>r!=="team-lead").join(", "),kickoffPrompt=`Your team is "${config.name}". Repo: ${config.repo}. Branch: ${config.name}. Worktree: ${config.worktreePath}. Wish slug: ${slug}. Your team members are: ${members} (already hired \u2014 genie work will spawn them automatically). Read the wish at .genie/wishes/${slug}/WISH.md and execute the full lifecycle autonomously.`;await handleWorkerSpawn2("team-lead",{provider:"claude",team:config.name,cwd:config.worktreePath,session:tmuxSession,initialPrompt:kickoffPrompt});let result=await(await Promise.resolve().then(() => (init_protocol_router(),exports_protocol_router))).sendMessage(config.worktreePath,"cli","team-lead",kickoffPrompt);if(!result.delivered)console.warn(`\u26A0 Backup delivery to team-lead failed: ${result.reason??"unknown"}`);console.log(" Leader: spawned and working")}async function autoDetectTeam(){let envTeam=process.env.GENIE_TEAM;if(envTeam)return envTeam;let teams=await listTeams2();if(teams.length===1)return teams[0].name;return null}async function printMembers(name,json2){let members=await listMembers(name);if(members===null)console.error(`Team "${name}" not found.`),process.exit(1);if(json2){console.log(JSON.stringify(members,null,2));return}if(members.length===0){console.log(`Team "${name}" has no members. Hire agents with: genie team hire <agent> --team ${name}`);return}console.log(""),console.log(`MEMBERS of "${name}"`),console.log("-".repeat(60));for(let m of members)console.log(` ${m}`);console.log("")}async function printTeams(json2,includeArchived){let teams=await listTeams2(includeArchived);if(json2){console.log(JSON.stringify(teams,null,2));return}if(teams.length===0){console.log("No teams found. Create one with: genie team create <name> --repo <path>");return}console.log(""),console.log("TEAMS"),console.log("-".repeat(60));for(let t of teams)printTeamSummary(t);console.log("")}function printTeamSummary(t){let status=t.status??"in_progress",dimmed=status==="archived"?"\x1B[90m":"",reset2=status==="archived"?"\x1B[0m":"";console.log(` ${dimmed}${t.name} [${status}]${reset2}`),console.log(` Repo: ${t.repo}`),console.log(` Branch: ${t.name} (from ${t.baseBranch})`),console.log(` Worktree: ${t.worktreePath}`),console.log(` Members: ${t.members.length}`)}function registerTemplateCommands(program2){let tmpl=program2.command("template").description("Board template management");tmpl.command("list",{isDefault:!0}).description("List available templates").option("--json","Output as JSON").action(async(options)=>{let{listTemplates:listTemplates3}=await Promise.resolve().then(() => (init_template_service(),exports_template_service)),templates=await listTemplates3();if(options.json){console.log(JSON.stringify(templates,null,2));return}if(templates.length===0){console.log("No templates found.");return}let maxName=Math.max(...templates.map((t)=>t.name.length),4);for(let t of templates){let cols=t.columns?.length??0,tag=t.isBuiltin?" (builtin)":"";console.log(` ${padRight(t.name,maxName)} ${cols} columns${tag} ${t.id}`)}console.log(`
2629
+ ${mode}Closed ${result.closed} task${result.closed===1?"":"s"} from ${result.prsScanned} merged PR${result.prsScanned===1?"":"s"} (${result.alreadyShipped} already shipped)`)}function registerTaskCommands(program2){let task=program2.command("task").description("Task lifecycle management");task.command("create <title>").description("Create a new task").option("--type <type>","Task type","software").option("--priority <priority>","Priority: urgent, high, normal, low","normal").option("--due <date>","Due date (YYYY-MM-DD)").option("--start <date>","Start date (YYYY-MM-DD)").option("--tags <tags>","Comma-separated tag IDs").option("--parent <id>","Parent task ID or #seq").option("--assign <name>","Assign to local actor").option("--description <text>","Task description").option("--effort <effort>",'Estimated effort (e.g., "2h", "3 points")').option("--comment <msg>","Initial comment on the task").option("--project <name>","Create task in a specific project (overrides CWD)").option("--board <name>","Board name to assign task to").option("--gh <owner/repo#N>","Link to GitHub issue (sets external_id + external_url)").option("--external-id <id>","External tracker ID (e.g., JIRA-123)").option("--external-url <url>","External tracker URL").action(async(title,options)=>{try{await handleTaskCreate(title,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}});async function handleTaskList(options){let ts3=await getTaskService7(),filters={stage:options.stage,typeId:options.type,status:options.status,priority:options.priority,releaseId:options.release,dueBefore:options.dueBefore,projectName:options.project,boardName:options.board,externalId:options.gh?parseGhRef(options.gh).externalId:void 0,allProjects:options.all,includeArchived:options.all,limit:Number(options.limit)||100,offset:Number(options.offset)||0,...options.all?{limit:1e4}:{}},tasks;if(options.mine)tasks=await ts3.listTasksForActor(currentActor2(),filters);else tasks=await ts3.listTasks(filters);if(options.byColumn){if(!options.board)console.error("Error: --by-column requires --board"),process.exit(1);if(!options.includeDone)tasks=tasks.filter((t)=>t.status!=="done");await printByColumn(tasks,options.board);return}if(options.json){console.log(JSON.stringify(tasks,null,2));return}printTaskList(tasks,options.all)}task.command("list").description("List tasks with filters").option("--stage <stage>","Filter by stage").option("--type <type>","Filter by type").option("--status <status>","Filter by status").option("--priority <priority>","Filter by priority").option("--release <release>","Filter by release").option("--due-before <date>","Filter by due date").option("--mine","Show only tasks assigned to me").option("--project <name>","Show tasks for a specific project").option("--board <name>","Filter by board name").option("--gh <owner/repo#N>","Filter by GitHub issue link").option("--by-column","Group tasks by board column (kanban view)").option("--include-done","Include done tasks in kanban view (hidden by default)").option("--all","Show tasks from ALL projects").option("--limit <n>","Max number of tasks to return","100").option("--offset <n>","Skip first N tasks (for pagination)","0").option("--json","Output as JSON").action(async(options)=>{try{await handleTaskList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("show <id>").description("Show task detail (accepts task-id or #seq)").option("--json","Output as JSON").action(async(id,options)=>{try{let t=await(await getTaskService7()).getTask(id);if(!t)console.error(`Error: Task not found: ${id}`),process.exit(1);if(options.json){console.log(JSON.stringify(t,null,2));return}await printTaskDetail(t)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("link <id>").description("Link task to an external tracker (GitHub, Jira, etc.)").option("--gh <owner/repo#N>","Link to GitHub issue").option("--external-id <id>","External tracker ID").option("--external-url <url>","External tracker URL").action(async(id,options)=>{try{let ts3=await getTaskService7(),externalId,externalUrl;if(options.gh){let parsed=parseGhRef(options.gh);externalId=parsed.externalId,externalUrl=parsed.externalUrl}else if(options.externalId&&options.externalUrl)externalId=options.externalId,externalUrl=options.externalUrl;else console.error("Error: Provide --gh or both --external-id and --external-url."),process.exit(1);let t=await ts3.linkTask(id,externalId,externalUrl);if(!t)console.error(`Error: Task not found: ${id}`),process.exit(1);if(console.log(`Linked task #${t.seq} to ${externalId}`),t.externalUrl)console.log(` URL: ${t.externalUrl}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("move <id>").description("Move task to a new stage").requiredOption("--to <stage>","Target stage").option("--comment <msg>","Comment on the move").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.moveTask(id,options.to,actor,options.comment);console.log(`Moved task #${t.seq} to stage "${t.stage}".`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);if(message.includes("Invalid stage"))await handleInvalidStageError(id,message);console.error(`Error: ${message}`),process.exit(1)}}),task.command("assign <id>").description("Assign an actor to a task").requiredOption("--to <name>","Actor name").option("--role <role>","Actor role","assignee").option("--comment <msg>","Comment on the assignment").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2();if(await ts3.assignTask(id,localActor2(options.to),options.role,{}),options.comment)await ts3.commentOnTask(id,actor,options.comment);console.log(`Assigned "${options.to}" as ${options.role??"assignee"} on task ${id}.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("tag <id> <tags...>").description("Add tags to a task").action(async(id,tags)=>{try{await(await getTaskService7()).tagTask(id,tags,currentActor2()),console.log(`Tagged task ${id} with: ${tags.join(", ")}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("comment <id> <message>").description("Add a comment to a task").option("--reply-to <msgId>","Reply to a specific message ID").action(async(id,message,options)=>{try{let ts3=await getTaskService7(),replyTo=options.replyTo?Number(options.replyTo):void 0,msg=await ts3.commentOnTask(id,currentActor2(),message,void 0,replyTo);console.log(`Comment #${msg.id} added to task ${id}.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("block <id>").description("Mark task as blocked").requiredOption("--reason <reason>","Reason for blocking").option("--comment <msg>","Additional comment").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.blockTask(id,options.reason,actor,options.comment);console.log(`Task #${t.seq} blocked: ${options.reason}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("unblock <id>").description("Unblock a task").option("--comment <msg>","Comment on unblock").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.unblockTask(id,actor,options.comment);console.log(`Task #${t.seq} unblocked.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("done <id>").description("Mark task as done").option("--comment <msg>","Comment on completion").action(async(id,options)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.markDone(id,actor,options.comment);console.log(`Task #${t.seq} marked as done.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("checkout <id>").description("Atomically claim a task for execution").action(async(id)=>{try{let ts3=await getTaskService7(),runId=getRunId(),t=await ts3.checkoutTask(id,runId);console.log(`Checked out task #${t.seq} for run: ${runId}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("release <id>").description("Release task checkout claim").action(async(id)=>{try{let ts3=await getTaskService7(),runId=getRunId(),t=await ts3.releaseTask(id,runId);console.log(`Released task #${t.seq} from run: ${runId}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("unlock <id>").description("Force-release a stale checkout (admin override)").action(async(id)=>{try{let t=await(await getTaskService7()).forceUnlockTask(id);console.log(`Force-unlocked task #${t.seq}.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("close-merged").description("Auto-close tasks whose wish slugs match recently merged PRs").option("--since <duration>",'Time window for merged PRs (e.g., "24h", "7d")',"24h").option("--dry-run","Show what would be closed without acting").option("--repo <owner/repo>","Override GitHub remote detection").action(async(options)=>{try{await handleCloseMerged(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("archive <id>").description("Archive a task (soft-delete \u2014 preserves all data)").action(async(id)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.archiveTask(id,actor);console.log(`Archived task #${t.seq}: ${t.title}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("unarchive <id>").description("Restore an archived task to its previous status").action(async(id)=>{try{let ts3=await getTaskService7(),actor=currentActor2(),t=await ts3.unarchiveTask(id,actor);console.log(`Unarchived task #${t.seq}: ${t.title} (status: ${t.status})`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),task.command("dep <id>").description("Manage task dependencies").option("--depends-on <id2>","This task depends on id2").option("--blocks <id2>","This task blocks id2").option("--relates-to <id2>","This task relates to id2").option("--remove <id2>","Remove dependency on id2").action(async(id,options)=>{try{let ts3=await getTaskService7();if(options.remove){if(await ts3.removeDependency(id,options.remove))console.log(`Removed dependency between ${id} and ${options.remove}.`);else console.log("No dependency found to remove.");return}if(options.dependsOn)await ts3.addDependency(id,options.dependsOn,"depends_on"),console.log(`${id} now depends on ${options.dependsOn}.`);if(options.blocks)await ts3.addDependency(id,options.blocks,"blocks"),console.log(`${id} now blocks ${options.blocks}.`);if(options.relatesTo)await ts3.addDependency(id,options.relatesTo,"relates_to"),console.log(`${id} now relates to ${options.relatesTo}.`);if(!options.dependsOn&&!options.blocks&&!options.relatesTo)console.error("Error: Specify --depends-on, --blocks, --relates-to, or --remove."),process.exit(1)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_team_manager();import{existsSync as existsSync38}from"fs";import{copyFile as copyFile2,cp as cp2,mkdir as mkdir8}from"fs/promises";import{join as join49,resolve as resolve7}from"path";function registerTeamNamespace(program2){let team=program2.command("team").description("Team lifecycle management");team.command("create <name>").description("Create a new team with a git worktree").requiredOption("--repo <path>","Path to the git repository").option("--branch <branch>","Base branch to create from","dev").option("--wish <slug>","Wish slug \u2014 auto-spawns a task leader with wish context").option("--tmux-session <name>","Tmux session to place team window in (default: derived from repo path)").option("--session <name>","Alias for --tmux-session (deprecated)").option("--no-spawn","Create team and copy wish without spawning the leader (useful for testing)").action(async(name,options)=>{try{let merged={...options,tmuxSession:options.tmuxSession??options.session};await handleTeamCreate(name,merged)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("hire <agent>").description('Add an agent to a team ("council" hires all 10 council members)').option("--team <name>","Team name (auto-detects from leader context if omitted)").action(async(agent,options)=>{try{let teamName=options.team??await autoDetectTeam();if(!teamName)console.error("Error: Could not detect team. Use --team <name> to specify."),process.exit(1);let added=await hireAgent(teamName,agent);if(added.length===0)console.log(`Agent "${agent}" is already a member of "${teamName}".`);else if(agent==="council"){console.log(`Hired ${added.length} council members to "${teamName}":`);for(let name of added)console.log(` + ${name}`)}else console.log(`Hired "${agent}" to team "${teamName}".`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("fire <agent>").description("Remove an agent from a team").option("--team <name>","Team name (auto-detects from leader context if omitted)").action(async(agent,options)=>{try{let teamName=options.team??await autoDetectTeam();if(!teamName)console.error("Error: Could not detect team. Use --team <name> to specify."),process.exit(1);if(await fireAgent(teamName,agent))console.log(`Fired "${agent}" from team "${teamName}".`);else console.error(`Agent "${agent}" is not a member of "${teamName}".`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("ls [name]").alias("list").description("List teams or members of a team").option("--all","Include archived teams").option("--json","Output as JSON").action(async(name,options)=>{try{if(name)await printMembers(name,options.json);else await printTeams(options.json,options.all)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("archive <name>").description("Archive a team (preserves all data, kills members)").action(async(name)=>{try{if(await archiveTeam(name))console.log(`Team "${name}" archived.`);else console.error(`Team "${name}" not found.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("unarchive <name>").description("Restore an archived team").action(async(name)=>{try{if(await unarchiveTeam(name))console.log(`Team "${name}" unarchived.`);else console.error(`Team "${name}" not found.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("disband <name>").description("Disband a team (archives \u2014 preserves data). Use `genie team archive` directly.").action(async(name)=>{try{if(await disbandTeam(name))console.log("Note: disband now archives the team. Use `genie team archive` directly."),console.log(`Team "${name}" disbanded (archived).`);else console.error(`Team "${name}" not found.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("done <name>").description("Mark a team as done and kill all members").action(async(name)=>{try{await setTeamStatus(name,"done"),await killTeamMembers(name),console.log(`Team "${name}" marked as done. All members killed.`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("blocked <name>").description("Mark a team as blocked and kill all members").action(async(name)=>{try{await setTeamStatus(name,"blocked"),await killTeamMembers(name),console.log(`Team "${name}" marked as blocked. All members killed.`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),team.command("cleanup").description("Kill tmux windows for done/archived teams").option("--dry-run","Show what would be cleaned without doing it").action(async(options)=>{try{await handleTeamCleanup(options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}async function handleTeamCreate(name,options){let resolvedRepo=resolve7(options.repo);if(options.wish){let wishPath=join49(resolvedRepo,".genie","wishes",options.wish,"WISH.md");if(!existsSync38(wishPath)){let cwdWishDir=join49(process.cwd(),".genie","wishes",options.wish),cwdWishPath=join49(cwdWishDir,"WISH.md");if(existsSync38(cwdWishPath)){let destDir=join49(resolvedRepo,".genie","wishes",options.wish);await mkdir8(destDir,{recursive:!0}),await cp2(cwdWishDir,destDir,{recursive:!0}),console.log(`Wish: copied ${options.wish}/WISH.md to repo`)}else console.error(`Error: Wish not found at ${wishPath}`),process.exit(1)}}let config=await createTeam(name,options.repo,options.branch),{findSessionByRepo:findSessionByRepo2}=await Promise.resolve().then(() => (init_agent_directory(),exports_agent_directory)),{resolveRepoSession:resolveRepoSession2}=await Promise.resolve().then(() => (init_tmux(),exports_tmux));if(config.tmuxSessionName=options.tmuxSession??await findSessionByRepo2(resolvedRepo)??await resolveRepoSession2(resolvedRepo),options.wish)config.wishSlug=options.wish;if(await updateTeamConfig(name,config),console.log(`Team "${config.name}" created.`),console.log(` Worktree: ${config.worktreePath}`),console.log(` Branch: ${config.name} (from ${config.baseBranch})`),config.tmuxSessionName)console.log(` Session: ${config.tmuxSessionName}`);if(config.nativeTeamsEnabled)console.log(" Native teams: enabled");if(options.wish&&options.spawn!==!1)await spawnLeaderWithWish(config,options.wish,options.repo,options.tmuxSession)}async function spawnLeaderWithWish(config,slug,repoPath,sessionOverride){let{handleWorkerSpawn:handleWorkerSpawn2}=await Promise.resolve().then(() => (init_agents(),exports_agents)),{findSessionByRepo:findSessionByRepo2}=await Promise.resolve().then(() => (init_agent_directory(),exports_agent_directory)),{resolveRepoSession:resolveRepoSession2}=await Promise.resolve().then(() => (init_tmux(),exports_tmux)),resolvedRepo=resolve7(repoPath),tmuxSession=sessionOverride??config.tmuxSessionName??await findSessionByRepo2(resolvedRepo)??await resolveRepoSession2(resolvedRepo);config.tmuxSessionName=tmuxSession,await updateTeamConfig(config.name,config);let sourceWishPath=join49(resolvedRepo,".genie","wishes",slug,"WISH.md");if(!existsSync38(sourceWishPath))console.error(`Error: Wish not found at ${sourceWishPath}`),process.exit(1);let destWishDir=join49(config.worktreePath,".genie","wishes",slug);await mkdir8(destWishDir,{recursive:!0});let destWishPath=join49(destWishDir,"WISH.md");await copyFile2(sourceWishPath,destWishPath),console.log(` Wish: copied ${slug}/WISH.md into worktree`);let standardTeam=["team-lead","engineer","reviewer","qa","fix"];for(let role of standardTeam)await hireAgent(config.name,role);console.log(` Team: hired ${standardTeam.join(", ")}`);let members=standardTeam.filter((r)=>r!=="team-lead").join(", "),kickoffPrompt=`Your team is "${config.name}". Repo: ${config.repo}. Branch: ${config.name}. Worktree: ${config.worktreePath}. Wish slug: ${slug}. Your team members are: ${members} (already hired \u2014 genie work will spawn them automatically). Read the wish at .genie/wishes/${slug}/WISH.md and execute the full lifecycle autonomously.`;await handleWorkerSpawn2("team-lead",{provider:"claude",team:config.name,cwd:config.worktreePath,session:tmuxSession,initialPrompt:kickoffPrompt});let result=await(await Promise.resolve().then(() => (init_protocol_router(),exports_protocol_router))).sendMessage(config.worktreePath,"cli","team-lead",kickoffPrompt);if(!result.delivered)console.warn(`\u26A0 Backup delivery to team-lead failed: ${result.reason??"unknown"}`);console.log(" Leader: spawned and working")}async function autoDetectTeam(){let envTeam=process.env.GENIE_TEAM;if(envTeam)return envTeam;let teams=await listTeams2();if(teams.length===1)return teams[0].name;return null}async function printMembers(name,json2){let members=await listMembers(name);if(members===null)console.error(`Team "${name}" not found.`),process.exit(1);if(json2){console.log(JSON.stringify(members,null,2));return}if(members.length===0){console.log(`Team "${name}" has no members. Hire agents with: genie team hire <agent> --team ${name}`);return}console.log(""),console.log(`MEMBERS of "${name}"`),console.log("-".repeat(60));for(let m of members)console.log(` ${m}`);console.log("")}async function printTeams(json2,includeArchived){let teams=await listTeams2(includeArchived);if(json2){console.log(JSON.stringify(teams,null,2));return}if(teams.length===0){console.log("No teams found. Create one with: genie team create <name> --repo <path>");return}console.log(""),console.log("TEAMS"),console.log("-".repeat(60));for(let t of teams)printTeamSummary(t);console.log("")}function printTeamSummary(t){let status=t.status??"in_progress",dimmed=status==="archived"?"\x1B[90m":"",reset2=status==="archived"?"\x1B[0m":"";console.log(` ${dimmed}${t.name} [${status}]${reset2}`),console.log(` Repo: ${t.repo}`),console.log(` Branch: ${t.name} (from ${t.baseBranch})`),console.log(` Worktree: ${t.worktreePath}`),console.log(` Members: ${t.members.length}`)}async function findTeamWindow(sessionName,teamName){let tmuxLib=await Promise.resolve().then(() => (init_tmux(),exports_tmux));if(!await tmuxLib.findSessionByName(sessionName))return null;try{return(await tmuxLib.listWindows(sessionName)).find((w)=>w.name===teamName||w.name===teamName.replace(/\./g,"_"))??null}catch{return null}}async function cleanupTeamWindow(t,dryRun){if(!t.tmuxSessionName)return null;let match=await findTeamWindow(t.tmuxSessionName,t.name);if(!match)return null;if(dryRun)return` [dry-run] Would kill window "${match.name}" in session "${t.tmuxSessionName}" (team "${t.name}" [${t.status}])`;if(!await(await Promise.resolve().then(() => (init_tmux(),exports_tmux))).killWindow(t.tmuxSessionName,match.name))return null;return` Killed window "${match.name}" in session "${t.tmuxSessionName}" (team "${t.name}")`}async function handleTeamCleanup(options){let cleanable=(await listTeams2(!0)).filter((t)=>t.status==="done"||t.status==="archived");if(cleanable.length===0){console.log("No done/archived teams to clean up.");return}let cleaned=0;for(let t of cleanable){let msg=await cleanupTeamWindow(t,options.dryRun===!0);if(msg)console.log(msg),cleaned++}let verb=options.dryRun?"Would clean":"Cleaned";if(cleaned===0)console.log("No tmux windows found for done/archived teams.");else console.log(`
2630
+ ${verb} ${cleaned} window${cleaned===1?"":"s"}.`)}function registerTemplateCommands(program2){let tmpl=program2.command("template").description("Board template management");tmpl.command("list",{isDefault:!0}).description("List available templates").option("--json","Output as JSON").action(async(options)=>{let{listTemplates:listTemplates3}=await Promise.resolve().then(() => (init_template_service(),exports_template_service)),templates=await listTemplates3();if(options.json){console.log(JSON.stringify(templates,null,2));return}if(templates.length===0){console.log("No templates found.");return}let maxName=Math.max(...templates.map((t)=>t.name.length),4);for(let t of templates){let cols=t.columns?.length??0,tag=t.isBuiltin?" (builtin)":"";console.log(` ${padRight(t.name,maxName)} ${cols} columns${tag} ${t.id}`)}console.log(`
2630
2631
  ${templates.length} template${templates.length===1?"":"s"}`)}),tmpl.command("show <name>").description("Show template details").option("--json","Output as JSON").action(async(name,options)=>{let{getTemplate:getTemplate2}=await Promise.resolve().then(() => (init_template_service(),exports_template_service)),t=await getTemplate2(name);if(!t)console.error(`Template "${name}" not found.`),process.exit(1);if(options.json){console.log(JSON.stringify(t,null,2));return}if(console.log(`
2631
2632
  Name: ${t.name}`),console.log(`ID: ${t.id}`),console.log(`Builtin: ${t.isBuiltin}`),console.log(`Description: ${t.description??"(none)"}`),t.columns&&t.columns.length>0)console.log(`Columns: ${t.columns.map((c)=>c.name).join(", ")}`);console.log("")}),tmpl.command("delete <name>").description("Delete a template").action(async(name)=>{let{deleteTemplate:deleteTemplate2,getTemplate:getTemplate2}=await Promise.resolve().then(() => (init_template_service(),exports_template_service)),t=await getTemplate2(name);if(!t)console.error(`Template "${name}" not found.`),process.exit(1);let ok=await deleteTemplate2(t.id);console.log(ok?`Deleted template "${t.name}".`:"Delete failed.")})}var _taskService8;async function getTaskService8(){if(!_taskService8)_taskService8=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService8}function printTypeTable(types4){console.log(` ${padRight("ID",20)} ${padRight("NAME",30)} ${padRight("STAGES",8)} BUILTIN`),console.log(` ${"\u2500".repeat(70)}`);for(let t of types4){let stageCount=Array.isArray(t.stages)?t.stages.length:0,builtin=t.isBuiltin?"yes":"no";console.log(` ${padRight(t.id,20)} ${padRight(t.name,30)} ${padRight(String(stageCount),8)} ${builtin}`)}console.log(`
2632
2633
  ${types4.length} type${types4.length===1?"":"s"}`)}function printTypePipeline(t){if(console.log(`