@automagik/genie 4.260509.8 → 4.260509.9

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
@@ -1258,7 +1258,7 @@ ${context}`}}}catch{return}}var BRAIN_PKG="@khal-os/brain",BRAIN_DIR="node_modul
1258
1258
  `+" genie agent send --to <a> \u2014 communicate directly"},{test:/sleep\s+\d+\s*&&\s*.*(?:capture-pane|tmux\s+list)/,message:`Consider using genie primitives instead of terminal polling:
1259
1259
  genie task status <slug>
1260
1260
  genie events list --since 5m`}]});import{existsSync as existsSync35,readFileSync as readFileSync25}from"fs";import{basename as basename4,join as join41}from"path";function readAgentNameFromSettings(cwd){let localSettings=join41(cwd,".claude","settings.local.json");if(!existsSync35(localSettings))return;try{return JSON.parse(readFileSync25(localSettings,"utf-8")).agentName||void 0}catch{return}}function nameFromCwd(cwd){let name=basename4(cwd);return name&&name!=="/"&&name!=="."?name:void 0}function resolveAgentName(payload){let cwd=payload.cwd;return payload.teammate_name||readEnvAgentId()||process.env.GENIE_AGENT_NAME||cwd&&readAgentNameFromSettings(cwd)||cwd&&nameFromCwd(cwd)||payload.session_id&&`session-${payload.session_id.slice(0,8)}`||HARNESS_AGENT}function resolveTeamName(payload){return payload.team_name??process.env.GENIE_TEAM??void 0}var HARNESS_AGENT="harness";var init_resolve_agent_name=__esm(()=>{init_env_identity()});async function emit(subject,event){try{let{publishSubjectEvent:publishSubjectEvent2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events));await publishSubjectEvent2(process.cwd(),subject,event)}catch(error2){let msg=error2 instanceof Error?error2.message:String(error2);console.warn(`[runtime-emit] event log unavailable: ${msg}`)}}async function emitToolCallEvent(payload){let{tool_name:toolName,tool_input:input}=payload;if(!toolName||!input)return;let agent=resolveAgentName(payload);await emit(`genie.tool.${agent}.call`,{timestamp:new Date().toISOString(),kind:"tool_call",agent,team:resolveTeamName(payload),text:summarizeToolCall(toolName,input),data:{toolCall:{name:toolName,input}},source:"hook"});return}async function emitMessageEvent(payload){let input=payload.tool_input;if(!input)return;let msgType=input.type;if(msgType&&msgType!=="message"&&msgType!=="broadcast")return;let to=input.to,content=input.content??input.message;if(!to||!content)return;let agent=resolveAgentName(payload),subject=msgType==="broadcast"?"genie.msg.broadcast":`genie.msg.${to}`;await emit(subject,{timestamp:new Date().toISOString(),kind:"message",agent,team:resolveTeamName(payload),peer:to,direction:"out",text:content,source:"hook"});return}async function emitUserPromptEvent(payload){let prompt2=payload.prompt;if(!prompt2)return;let agent=resolveAgentName(payload);await emit(`genie.user.${agent}.prompt`,{timestamp:new Date().toISOString(),kind:"user",agent,team:resolveTeamName(payload),text:prompt2,source:"hook"});return}async function emitAssistantResponseEvent(payload){let lastMessage=payload.last_assistant_message;if(!lastMessage)return;let agent=resolveAgentName(payload);await emit(`genie.agent.${agent}.response`,{timestamp:new Date().toISOString(),kind:"assistant",agent,team:resolveTeamName(payload),text:lastMessage,source:"hook"});return}function summarizeToolCall(name,input){switch(name){case"Read":case"Edit":case"Write":return`${name} ${input.file_path??""}`;case"Bash":return`$ ${String(input.command??"").split(`
1261
- `)[0]}`;case"Grep":return`Grep "${input.pattern}" ${input.path??""}`;case"Glob":return`Glob ${input.pattern}`;case"Agent":return`Agent: ${input.description??""}`;case"SendMessage":return`SendMessage \u2192 ${input.to}: ${String(input.message??"").slice(0,80)}`;default:return name}}var init_runtime_emit=__esm(()=>{init_resolve_agent_name()});import{existsSync as existsSync36,mkdirSync as mkdirSync18,readFileSync as readFileSync26,renameSync as renameSync7,writeFileSync as writeFileSync15}from"fs";import{homedir as homedir32}from"os";import{join as join42}from"path";function effectiveCacheFile(){let override=globalThis.__GENIE_SESSION_SYNC_CACHE_FILE;return typeof override==="string"&&override.length>0?override:DEFAULT_CACHE_FILE}function loadDiskCache(){if(diskCacheLoaded)return;diskCacheLoaded=!0;let hasOverrides=Object.values(_deps3).some((v)=>v!==null),testCacheOverridden=typeof globalThis.__GENIE_SESSION_SYNC_CACHE_FILE==="string";if((hasOverrides||!1||!1)&&!testCacheOverridden)return;try{let cacheFile=effectiveCacheFile();if(!existsSync36(cacheFile))return;let parsed=JSON.parse(readFileSync26(cacheFile,"utf-8"));for(let[executorId,sessionId]of Object.entries(parsed))if(typeof sessionId==="string"&&sessionId.length>0)syncedSessions.set(executorId,sessionId)}catch{}}function trimCache(){while(syncedSessions.size>MAX_CACHE_ENTRIES){let oldest=syncedSessions.keys().next().value;if(oldest===void 0)break;syncedSessions.delete(oldest)}}function persistDiskCache(){let hasOverrides=Object.values(_deps3).some((v)=>v!==null),testCacheOverridden=typeof globalThis.__GENIE_SESSION_SYNC_CACHE_FILE==="string";if((hasOverrides||!1||!1)&&!testCacheOverridden)return;try{let cacheFile=effectiveCacheFile();mkdirSync18(join42(cacheFile,".."),{recursive:!0}),trimCache();let obj=Object.fromEntries(syncedSessions),tmp=`${cacheFile}.tmp.${process.pid}`;writeFileSync15(tmp,JSON.stringify(obj)),renameSync7(tmp,cacheFile)}catch{}}async function resolveDeps2(){let needsAgentMod=!_deps3.getAgent||!_deps3.getAgentByName,[agentMod,execMod,audit]=await Promise.all([needsAgentMod?Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)):null,_deps3.getExecutor&&_deps3.updateClaudeSessionId?null:Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),_deps3.emitAuditEvent?null:Promise.resolve().then(() => (init_audit(),exports_audit))]);return{getAgent:_deps3.getAgent??agentMod.getAgent,getAgentByName:_deps3.getAgentByName??agentMod.getAgentByName,getExecutor:_deps3.getExecutor??execMod.getExecutor,updateClaudeSessionId:_deps3.updateClaudeSessionId??execMod.updateClaudeSessionId,emitAuditEvent:_deps3.emitAuditEvent??audit.recordAuditEvent}}function shouldSkipSync(payload){let sessionId=payload.session_id;if(!sessionId||typeof sessionId!=="string")return null;let hasOverrides=Object.values(_deps3).some((v)=>v!==null),agentId=readEnvAgentId(),agentName=readEnvAgentName()??payload.teammate_name,teamName=process.env.GENIE_TEAM??payload.team_name;if(!teamName)return null;if(!agentId&&!agentName)return null;return{sessionId,agentName:agentName??agentId??"",agentId,teamName}}async function sessionSync(payload){try{let ctx=shouldSkipSync(payload);if(!ctx)return;loadDiskCache();let deps=await resolveDeps2(),executorId=(ctx.agentId?await deps.getAgent(ctx.agentId):await deps.getAgentByName(ctx.agentName,ctx.teamName))?.currentExecutorId;if(!executorId)return;if(syncedSessions.get(executorId)===ctx.sessionId)return;let executor=await deps.getExecutor(executorId);if(!executor)return;let oldSessionId=executor.claudeSessionId??null;if(oldSessionId===ctx.sessionId){syncedSessions.set(executorId,ctx.sessionId),persistDiskCache();return}let isTerminal=TERMINAL_EXECUTOR_STATES.has(executor.state??"");if(oldSessionId!==null&&isTerminal){await deps.emitAuditEvent("executor",executorId,"session.divergence_preserved",ctx.agentName,{stored_session_id:oldSessionId,live_session_id:ctx.sessionId,executor_state:executor.state??null,team:ctx.teamName,reason:"terminal_executor_is_recovery_anchor"}),syncedSessions.set(executorId,ctx.sessionId),persistDiskCache();return}await deps.updateClaudeSessionId(executorId,ctx.sessionId),await deps.emitAuditEvent("executor",executorId,"session.reconciled",ctx.agentName,{old_session_id:oldSessionId,new_session_id:ctx.sessionId,team:ctx.teamName}),syncedSessions.set(executorId,ctx.sessionId),persistDiskCache()}catch(err){let msg=err instanceof Error?err.message:String(err);console.warn(`[session-sync] ${msg}`)}return}var syncedSessions,GENIE_HOME3,DEFAULT_CACHE_FILE,diskCacheLoaded=!1,MAX_CACHE_ENTRIES=1000,_deps3,TERMINAL_EXECUTOR_STATES;var init_session_sync=__esm(()=>{init_env_identity();syncedSessions=new Map,GENIE_HOME3=process.env.GENIE_HOME??join42(homedir32(),".genie"),DEFAULT_CACHE_FILE=join42(GENIE_HOME3,"cache","session-sync.json");_deps3={getAgent:null,getAgentByName:null,getExecutor:null,updateClaudeSessionId:null,emitAuditEvent:null};TERMINAL_EXECUTOR_STATES=new Set(["done","error","terminated"])});function setRegistry(next){registryRef=Object.freeze([...next])}function getRegistry(){return registryRef}function resolveHandlers(event,toolName){return registryRef.filter((h)=>{if(h.event!==event)return!1;if(h.matcher&&toolName&&!h.matcher.test(toolName))return!1;if(h.matcher&&!toolName)return!1;return!0}).sort((a,b2)=>a.priority-b2.priority)}function hookDebug(handlerName,decision,elapsedMs){if(process.env.GENIE_HOOK_DEBUG==="1")console.error(`[hook-debug] ${handlerName} \u2192 ${decision} (${elapsedMs}ms)`)}async function runHandler(handler,payload,currentInput,isBlocking){let handlerPayload={...payload};if(currentInput)handlerPayload.tool_input=currentInput;let start=Date.now(),agentId=resolveAgentName(handlerPayload),teamId=resolveTeamName(handlerPayload),span=isWideEmitEnabled()?startSpan("hook.delivery",{hook_name:handler.name,agent_id:agentId,tool:payload.tool_name,event:payload.hook_event_name},{source_subsystem:"hooks",ctx:getAmbient()??void 0,agent:agentId,team:teamId}):null;try{let result2=await handler.fn(handlerPayload);if(hookDebug(handler.name,result2?.decision??result2?.hookSpecificOutput?.permissionDecision??"allow",Date.now()-start),span)endSpan(span,{hook_name:handler.name,agent_id:agentId,status:result2?.decision==="deny"?"rejected":"ok"},{source_subsystem:"hooks",agent:agentId,team:teamId});return result2}catch(err){let msg=err instanceof Error?err.message:String(err);if(console.error(`[genie-hook] Handler "${handler.name}" threw: ${msg}`),span)endSpan(span,{hook_name:handler.name,agent_id:agentId,status:"error",stderr_excerpt:msg.slice(0,1024)},{source_subsystem:"hooks",agent:agentId,team:teamId});if(isBlocking)return hookDebug(handler.name,"deny (crash)",Date.now()-start),{decision:"deny",reason:`handler crashed: ${msg}`};hookDebug(handler.name,"allow (crash, non-blocking)",Date.now()-start);return}}function buildDenyResponse(handler,reason,hookEventName){if(hookEventName==="PreToolUse")return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:reason??`Denied by handler: ${handler.name}`}};return{decision:"block",reason:reason??`Denied by handler: ${handler.name}`}}function buildBlockingResponse(hookEventName,contextMessages,currentInput,originalInput,toolName){let response={},hasContext=contextMessages.length>0,hasInputChange=currentInput&&originalInput&&JSON.stringify(currentInput)!==JSON.stringify(originalInput);if(hookEventName==="PreToolUse"&&typeof toolName==="string"&&NON_INTERCEPTABLE_PRE_TOOL_USE_TOOLS.includes(toolName))return response;if(hasInputChange)response.updatedInput=currentInput;if(hookEventName==="PreToolUse"&&(hasContext||hasInputChange)){let output={hookEventName:"PreToolUse"};if(hasContext)output.additionalContext=contextMessages.join(`
1261
+ `)[0]}`;case"Grep":return`Grep "${input.pattern}" ${input.path??""}`;case"Glob":return`Glob ${input.pattern}`;case"Agent":return`Agent: ${input.description??""}`;case"SendMessage":return`SendMessage \u2192 ${input.to}: ${String(input.message??"").slice(0,80)}`;default:return name}}var init_runtime_emit=__esm(()=>{init_resolve_agent_name()});import{existsSync as existsSync36,mkdirSync as mkdirSync18,readFileSync as readFileSync26,renameSync as renameSync8,writeFileSync as writeFileSync15}from"fs";import{homedir as homedir32}from"os";import{join as join42}from"path";function effectiveCacheFile(){let override=globalThis.__GENIE_SESSION_SYNC_CACHE_FILE;return typeof override==="string"&&override.length>0?override:DEFAULT_CACHE_FILE}function loadDiskCache(){if(diskCacheLoaded)return;diskCacheLoaded=!0;let hasOverrides=Object.values(_deps3).some((v)=>v!==null),testCacheOverridden=typeof globalThis.__GENIE_SESSION_SYNC_CACHE_FILE==="string";if((hasOverrides||!1||!1)&&!testCacheOverridden)return;try{let cacheFile=effectiveCacheFile();if(!existsSync36(cacheFile))return;let parsed=JSON.parse(readFileSync26(cacheFile,"utf-8"));for(let[executorId,sessionId]of Object.entries(parsed))if(typeof sessionId==="string"&&sessionId.length>0)syncedSessions.set(executorId,sessionId)}catch{}}function trimCache(){while(syncedSessions.size>MAX_CACHE_ENTRIES){let oldest=syncedSessions.keys().next().value;if(oldest===void 0)break;syncedSessions.delete(oldest)}}function persistDiskCache(){let hasOverrides=Object.values(_deps3).some((v)=>v!==null),testCacheOverridden=typeof globalThis.__GENIE_SESSION_SYNC_CACHE_FILE==="string";if((hasOverrides||!1||!1)&&!testCacheOverridden)return;try{let cacheFile=effectiveCacheFile();mkdirSync18(join42(cacheFile,".."),{recursive:!0}),trimCache();let obj=Object.fromEntries(syncedSessions),tmp=`${cacheFile}.tmp.${process.pid}`;writeFileSync15(tmp,JSON.stringify(obj)),renameSync8(tmp,cacheFile)}catch{}}async function resolveDeps2(){let needsAgentMod=!_deps3.getAgent||!_deps3.getAgentByName,[agentMod,execMod,audit]=await Promise.all([needsAgentMod?Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)):null,_deps3.getExecutor&&_deps3.updateClaudeSessionId?null:Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),_deps3.emitAuditEvent?null:Promise.resolve().then(() => (init_audit(),exports_audit))]);return{getAgent:_deps3.getAgent??agentMod.getAgent,getAgentByName:_deps3.getAgentByName??agentMod.getAgentByName,getExecutor:_deps3.getExecutor??execMod.getExecutor,updateClaudeSessionId:_deps3.updateClaudeSessionId??execMod.updateClaudeSessionId,emitAuditEvent:_deps3.emitAuditEvent??audit.recordAuditEvent}}function shouldSkipSync(payload){let sessionId=payload.session_id;if(!sessionId||typeof sessionId!=="string")return null;let hasOverrides=Object.values(_deps3).some((v)=>v!==null),agentId=readEnvAgentId(),agentName=readEnvAgentName()??payload.teammate_name,teamName=process.env.GENIE_TEAM??payload.team_name;if(!teamName)return null;if(!agentId&&!agentName)return null;return{sessionId,agentName:agentName??agentId??"",agentId,teamName}}async function sessionSync(payload){try{let ctx=shouldSkipSync(payload);if(!ctx)return;loadDiskCache();let deps=await resolveDeps2(),executorId=(ctx.agentId?await deps.getAgent(ctx.agentId):await deps.getAgentByName(ctx.agentName,ctx.teamName))?.currentExecutorId;if(!executorId)return;if(syncedSessions.get(executorId)===ctx.sessionId)return;let executor=await deps.getExecutor(executorId);if(!executor)return;let oldSessionId=executor.claudeSessionId??null;if(oldSessionId===ctx.sessionId){syncedSessions.set(executorId,ctx.sessionId),persistDiskCache();return}let isTerminal=TERMINAL_EXECUTOR_STATES.has(executor.state??"");if(oldSessionId!==null&&isTerminal){await deps.emitAuditEvent("executor",executorId,"session.divergence_preserved",ctx.agentName,{stored_session_id:oldSessionId,live_session_id:ctx.sessionId,executor_state:executor.state??null,team:ctx.teamName,reason:"terminal_executor_is_recovery_anchor"}),syncedSessions.set(executorId,ctx.sessionId),persistDiskCache();return}await deps.updateClaudeSessionId(executorId,ctx.sessionId),await deps.emitAuditEvent("executor",executorId,"session.reconciled",ctx.agentName,{old_session_id:oldSessionId,new_session_id:ctx.sessionId,team:ctx.teamName}),syncedSessions.set(executorId,ctx.sessionId),persistDiskCache()}catch(err){let msg=err instanceof Error?err.message:String(err);console.warn(`[session-sync] ${msg}`)}return}var syncedSessions,GENIE_HOME3,DEFAULT_CACHE_FILE,diskCacheLoaded=!1,MAX_CACHE_ENTRIES=1000,_deps3,TERMINAL_EXECUTOR_STATES;var init_session_sync=__esm(()=>{init_env_identity();syncedSessions=new Map,GENIE_HOME3=process.env.GENIE_HOME??join42(homedir32(),".genie"),DEFAULT_CACHE_FILE=join42(GENIE_HOME3,"cache","session-sync.json");_deps3={getAgent:null,getAgentByName:null,getExecutor:null,updateClaudeSessionId:null,emitAuditEvent:null};TERMINAL_EXECUTOR_STATES=new Set(["done","error","terminated"])});function setRegistry(next){registryRef=Object.freeze([...next])}function getRegistry(){return registryRef}function resolveHandlers(event,toolName){return registryRef.filter((h)=>{if(h.event!==event)return!1;if(h.matcher&&toolName&&!h.matcher.test(toolName))return!1;if(h.matcher&&!toolName)return!1;return!0}).sort((a,b2)=>a.priority-b2.priority)}function hookDebug(handlerName,decision,elapsedMs){if(process.env.GENIE_HOOK_DEBUG==="1")console.error(`[hook-debug] ${handlerName} \u2192 ${decision} (${elapsedMs}ms)`)}async function runHandler(handler,payload,currentInput,isBlocking){let handlerPayload={...payload};if(currentInput)handlerPayload.tool_input=currentInput;let start=Date.now(),agentId=resolveAgentName(handlerPayload),teamId=resolveTeamName(handlerPayload),span=isWideEmitEnabled()?startSpan("hook.delivery",{hook_name:handler.name,agent_id:agentId,tool:payload.tool_name,event:payload.hook_event_name},{source_subsystem:"hooks",ctx:getAmbient()??void 0,agent:agentId,team:teamId}):null;try{let result2=await handler.fn(handlerPayload);if(hookDebug(handler.name,result2?.decision??result2?.hookSpecificOutput?.permissionDecision??"allow",Date.now()-start),span)endSpan(span,{hook_name:handler.name,agent_id:agentId,status:result2?.decision==="deny"?"rejected":"ok"},{source_subsystem:"hooks",agent:agentId,team:teamId});return result2}catch(err){let msg=err instanceof Error?err.message:String(err);if(console.error(`[genie-hook] Handler "${handler.name}" threw: ${msg}`),span)endSpan(span,{hook_name:handler.name,agent_id:agentId,status:"error",stderr_excerpt:msg.slice(0,1024)},{source_subsystem:"hooks",agent:agentId,team:teamId});if(isBlocking)return hookDebug(handler.name,"deny (crash)",Date.now()-start),{decision:"deny",reason:`handler crashed: ${msg}`};hookDebug(handler.name,"allow (crash, non-blocking)",Date.now()-start);return}}function buildDenyResponse(handler,reason,hookEventName){if(hookEventName==="PreToolUse")return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:reason??`Denied by handler: ${handler.name}`}};return{decision:"block",reason:reason??`Denied by handler: ${handler.name}`}}function buildBlockingResponse(hookEventName,contextMessages,currentInput,originalInput,toolName){let response={},hasContext=contextMessages.length>0,hasInputChange=currentInput&&originalInput&&JSON.stringify(currentInput)!==JSON.stringify(originalInput);if(hookEventName==="PreToolUse"&&typeof toolName==="string"&&NON_INTERCEPTABLE_PRE_TOOL_USE_TOOLS.includes(toolName))return response;if(hasInputChange)response.updatedInput=currentInput;if(hookEventName==="PreToolUse"&&(hasContext||hasInputChange)){let output={hookEventName:"PreToolUse"};if(hasContext)output.additionalContext=contextMessages.join(`
1262
1262
  `);if(hasInputChange)output.permissionDecision="allow",output.updatedInput=currentInput;response.hookSpecificOutput=output}if(hookEventName==="UserPromptSubmit"&&hasContext)response.hookSpecificOutput={hookEventName:"UserPromptSubmit",additionalContext:contextMessages.join(`
1263
1263
  `)};return response}async function executeBlockingChain(matched,payload){let currentInput=payload.tool_input?{...payload.tool_input}:void 0,contextMessages=[],hookEventName=payload.hook_event_name;for(let handler of matched){let result2=await runHandler(handler,payload,currentInput,!0);if(!result2)continue;if(result2.decision==="deny")return buildDenyResponse(handler,result2.reason,hookEventName);if(result2.hookSpecificOutput?.additionalContext)contextMessages.push(result2.hookSpecificOutput.additionalContext);let inputUpdate=result2.hookSpecificOutput?.updatedInput??result2.updatedInput;if(inputUpdate)currentInput={...currentInput,...inputUpdate}}return buildBlockingResponse(hookEventName,contextMessages,currentInput,payload.tool_input,payload.tool_name)}async function executeNonBlockingHandlers(matched,payload){await Promise.allSettled(matched.map((h)=>h.fn(payload).catch((err)=>{let msg=err instanceof Error?err.message:String(err);console.error(`[genie-hook] Handler "${h.name}" threw: ${msg}`)})))}async function dispatch(stdin){let payload;try{payload=JSON.parse(stdin)}catch{return console.error("[genie-hook] Invalid JSON on stdin"),""}let event=payload.hook_event_name;if(!event)return console.error("[genie-hook] Missing hook_event_name in payload"),"";let toolName=payload.tool_name,matched=resolveHandlers(event,toolName);if(matched.length===0)return"";if(isBlockingEvent(event)){let result2=await executeBlockingChain(matched,payload);if(Object.keys(result2).length>0)return JSON.stringify(result2);return""}return await executeNonBlockingHandlers(matched,payload),""}var BUILTIN_MANIFEST_PATH="src/hooks/index.ts",builtinHandlers,registryRef,NON_INTERCEPTABLE_PRE_TOOL_USE_TOOLS;var init_hooks=__esm(()=>{init_emit();init_trace_context();init_audit_context();init_brain_inject();init_branch_guard();init_codex_inbox_deliver();init_freshness();init_identity_inject();init_orchestration_guard();init_runtime_emit();init_session_sync();init_resolve_agent_name();init_types2();builtinHandlers=[{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"branch-guard",event:"PreToolUse",matcher:/^Bash$/,priority:1,fn:branchGuard},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"orchestration-guard",event:"PreToolUse",matcher:/^Bash$/,priority:2,fn:orchestrationGuard},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"brain-inject",event:"PreToolUse",matcher:/.*/,priority:5,fn:brainInject},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"freshness",event:"PreToolUse",matcher:/^Read$/,priority:8,fn:freshness},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"audit-context",event:"PreToolUse",matcher:/^(Write|Edit)$/,priority:8,fn:auditContext},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"identity-inject",event:"PreToolUse",matcher:/^SendMessage$/,priority:10,fn:identityInject},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"auto-spawn",event:"PreToolUse",matcher:/^SendMessage$/,priority:20,fn:autoSpawn},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"runtime-emit-tool",event:"PreToolUse",matcher:/.*/,priority:30,fn:emitToolCallEvent},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"runtime-emit-msg",event:"PostToolUse",matcher:/^SendMessage$/,priority:30,fn:emitMessageEvent},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"codex-inbox-deliver",event:"UserPromptSubmit",priority:25,fn:codexInboxDeliver},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"runtime-emit-user-prompt",event:"UserPromptSubmit",priority:30,fn:emitUserPromptEvent},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"runtime-emit-assistant-response",event:"Stop",priority:30,fn:emitAssistantResponseEvent},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"session-sync-tool",event:"PreToolUse",matcher:/.*/,priority:35,fn:sessionSync},{version:"1",source:"builtin",manifest_path:BUILTIN_MANIFEST_PATH,name:"session-sync-prompt",event:"UserPromptSubmit",priority:35,fn:sessionSync}],registryRef=Object.freeze([...builtinHandlers]);NON_INTERCEPTABLE_PRE_TOOL_USE_TOOLS=["AskUserQuestion"]});var exports_interactivity={};__export(exports_interactivity,{isInteractive:()=>isInteractive,installWorkspaceCheck:()=>installWorkspaceCheck,ensureWorkspace:()=>ensureWorkspace,commandRequiresWorkspace:()=>commandRequiresWorkspace});function isInteractive(){if(!process.stdout.isTTY)return!1;if(process.env.CI)return!1;if(process.argv.includes("--no-interactive"))return!1;return!0}function getRootCommandName(cmd){let current=cmd;while(current.parent?.parent)current=current.parent;return current.name()}function commandRequiresWorkspace(cmd){return!WORKSPACE_EXEMPT.has(getRootCommandName(cmd))}async function ensureWorkspace(){if(findWorkspace())return;if(!isInteractive())console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{confirm}=await Promise.resolve().then(() => (init_esm14(),exports_esm));if(!await confirm({message:"No workspace found. Initialize? [Y/n]",default:!0}))console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{mkdirSync:mkdirSync19,writeFileSync:writeFileSync16}=await import("fs"),{basename:basename5,join:join43}=await import("path"),cwd=process.cwd(),genieDir=join43(cwd,".genie");mkdirSync19(genieDir,{recursive:!0});let config={name:basename5(cwd),agents:{defaults:{}},tmux:{socket:"genie"},sdk:{}};writeFileSync16(join43(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
1264
1264
  `),console.log(`Workspace initialized: ${cwd}`)}function installWorkspaceCheck(program2){program2.hook("preAction",async(_thisCommand,actionCommand)=>{if(!commandRequiresWorkspace(actionCommand))return;await ensureWorkspace()})}var WORKSPACE_EXEMPT;var init_interactivity=__esm(()=>{init_workspace();WORKSPACE_EXEMPT=new Set(["init","setup","doctor","update","uninstall","shortcuts","team","version","help","hook"])});function dropSensitiveKeys(obj){let result2={};for(let key of Object.keys(obj)){if(SENSITIVE_OTEL_KEYS.has(key))continue;result2[key]=obj[key]}return result2}function extractValue(kv){let v=kv.value;if(v.stringValue!==void 0)return v.stringValue;if(v.intValue!==void 0)return typeof v.intValue==="string"?Number.parseInt(v.intValue,10):v.intValue;if(v.doubleValue!==void 0)return v.doubleValue;if(v.boolValue!==void 0)return v.boolValue;return}function attrsToObject(attrs){if(!attrs)return{};let obj={};for(let kv of attrs)obj[kv.key]=extractValue(kv);return obj}function extractResourceContext(resource){let raw=attrsToObject(resource?.attributes),filtered={};for(let key of Object.keys(raw)){if(SENSITIVE_OTEL_KEYS.has(key))continue;if(!RESOURCE_ATTR_ALLOWLIST.has(key))continue;filtered[key]=raw[key]}return{agentName:filtered["agent.name"],teamName:filtered["team.name"],wishSlug:filtered["wish.slug"],sessionId:filtered["session.id"],agentRole:filtered["agent.role"]}}function mapEventToEntityType(eventName){if(eventName.includes("tool_result"))return"otel_tool";if(eventName.includes("api_request")||eventName.includes("api_error"))return"otel_api";if(eventName.includes("user_prompt"))return"otel_prompt";if(eventName.includes("tool_decision"))return"otel_decision";return"otel_event"}function parseValidPort(raw){if(!raw)return null;let parsed=Number.parseInt(raw,10);if(!Number.isNaN(parsed)&&parsed>0&&parsed<65536)return parsed;return null}function parseProbeMax(){let parsed=Number.parseInt(process.env.GENIE_OTEL_PORT_PROBE_MAX??"",10);if(!Number.isNaN(parsed)&&parsed>0)return parsed;return DEFAULT_OTEL_PORT_PROBE_MAX}function getConfiguredOtelPort(){let envPort=parseValidPort(process.env.GENIE_OTEL_PORT);if(envPort!==null)return{port:envPort,explicit:!0};return{port:getAuxiliaryPortBase()+1,explicit:!1}}function getCandidatePorts(startPort,explicit){if(explicit)return[startPort];let probeCount=Math.min(parseProbeMax(),Math.max(1,65535-startPort+1));return Array.from({length:probeCount},(_,index)=>startPort+index)}function formatPortList(ports){if(ports.length===1)return String(ports[0]);return`${ports[0]}-${ports[ports.length-1]}`}function isPortBusyError(err){if(err&&typeof err==="object"&&"code"in err&&err.code==="EADDRINUSE")return!0;let message=err instanceof Error?err.message:String(err);return message.includes("EADDRINUSE")||message.includes("address already in use")||/Failed to start server\. Is port \d+ in use\?/i.test(message)||/\bis in use\b/i.test(message)}function resolveEntityId(ctx){return ctx.sessionId??(ctx.agentName?`agent:${ctx.agentName}`:"unknown")}function mergeContext(details,ctx){if(ctx.teamName)details.team=ctx.teamName;if(ctx.wishSlug)details.wish_slug=ctx.wishSlug;if(ctx.agentRole)details.agent_role=ctx.agentRole;if(ctx.sessionId)details.session_id=ctx.sessionId}function logRecordToRow(record,ctx){let logAttrs=dropSensitiveKeys(attrsToObject(record.attributes)),eventName=logAttrs["event.name"]??record.body?.stringValue??"unknown",details={...logAttrs,event_name:eventName};if(mergeContext(details,ctx),record.severityText)details.severity=record.severityText;if(record.body?.kvlistValue?.values)Object.assign(details,dropSensitiveKeys(attrsToObject(record.body.kvlistValue.values)));return{entity_type:mapEventToEntityType(eventName),entity_id:resolveEntityId(ctx),event_type:eventName,actor:ctx.agentName??null,details}}function processLogs(payload){let rows=[];for(let resourceLog of payload.resourceLogs??[]){let ctx=extractResourceContext(resourceLog.resource);for(let scopeLog of resourceLog.scopeLogs??[])for(let record of scopeLog.logRecords??[])rows.push(logRecordToRow(record,ctx))}return rows}function buildMetricRow(metricName,entityId,actor,details){return{entity_type:"otel_metric",entity_id:entityId,event_type:metricName,actor,details}}function processSumGaugePoints(dataPoints,metricName,unit,entityId,ctx){return dataPoints.map((dp)=>{let dpAttrs=dropSensitiveKeys(attrsToObject(dp.attributes)),value=dp.asDouble??(dp.asInt!==void 0?Number(dp.asInt):void 0),details={metric_name:metricName,value,...dpAttrs};if(unit)details.unit=unit;return mergeContext(details,ctx),buildMetricRow(metricName,entityId,ctx.agentName??null,details)})}function metricToRows(metric,ctx){let metricName=metric.name??"unknown_metric",entityId=resolveEntityId(ctx),dataPoints=metric.sum?.dataPoints??metric.gauge?.dataPoints??[],rows=processSumGaugePoints(dataPoints,metricName,metric.unit,entityId,ctx);for(let dp of metric.histogram?.dataPoints??[]){let dpAttrs=dropSensitiveKeys(attrsToObject(dp.attributes)),details={metric_name:metricName,sum:dp.sum,count:dp.count!==void 0?Number(dp.count):void 0,...dpAttrs};if(metric.unit)details.unit=metric.unit;mergeContext(details,ctx),rows.push(buildMetricRow(metricName,entityId,ctx.agentName??null,details))}return rows}function processMetrics(payload){let rows=[];for(let resourceMetric of payload.resourceMetrics??[]){let ctx=extractResourceContext(resourceMetric.resource);for(let scopeMetric of resourceMetric.scopeMetrics??[])for(let metric of scopeMetric.metrics??[])rows.push(...metricToRows(metric,ctx))}return rows}async function flushToPg(rows){if(rows.length===0)return;try{let{getConnection:getConnection2,isAvailable:isAvailable2}=await Promise.resolve().then(() => (init_db(),exports_db));if(!await isAvailable2())return;let sql=await getConnection2();await sql`
@@ -1320,7 +1320,7 @@ Run 'genie agent list' to list agents.`)}async function resolveTarget(target,opt
1320
1320
  `)}var STATE_ICONS;var init_brief=__esm(()=>{init_db();init_mailbox();init_runtime_events();init_team_manager();STATE_ICONS={working:"\u25CF",idle:"\u25CB",error:"\u2718"}});import{readFile as readFile5,rename as rename2,writeFile as writeFile5}from"fs/promises";function stripDerivedFields(config){let out={...config};for(let key of DERIVED_KEYS)delete out[key];return out}async function parseAgentYaml(path3){let raw;try{raw=await readFile5(path3,"utf-8")}catch(err){let message=err instanceof Error?err.message:String(err);throw Error(`Failed to read agent.yaml at ${path3}: ${message}`)}let parsed;try{parsed=load(raw)}catch(err){let message=err instanceof Error?err.message:String(err);throw Error(`Malformed YAML in ${path3}: ${message}`)}let input=parsed===null||parsed===void 0?{}:parsed;if(typeof input!=="object"||Array.isArray(input))throw Error(`agent.yaml at ${path3} must be a YAML mapping, got ${Array.isArray(input)?"array":typeof input}`);let result2=AgentConfigSchema.safeParse(input);if(!result2.success)throw Error(`Invalid agent.yaml at ${path3}: ${formatZodError(result2.error)}`);return result2.data}function formatZodError(error2){return error2.issues.map((issue)=>{let path3=issue.path.length>0?issue.path.join("."):"(root)";if(issue.code==="unrecognized_keys"){let keys=issue.keys.join(", ");return`unknown field(s) at ${path3}: ${keys}`}return`${path3}: ${issue.message}`}).join("; ")}async function writeAgentYaml(path3,config){let stripped=stripDerivedFields(config),yamlStr=dump(stripped,{lineWidth:-1,noRefs:!0,sortKeys:!1,quotingType:'"'});await acquireLock(path3);try{let tmpPath=`${path3}.tmp`;await writeFile5(tmpPath,yamlStr,"utf-8"),await rename2(tmpPath,path3)}finally{await releaseLock(path3)}}function extractFrontmatterFromAgentsMd(content){if(!content.startsWith(`---
1321
1321
  `))return{frontmatter:null,body:content};let after=content.slice(4),frontmatter,afterClose;if(after.startsWith("---"))frontmatter="",afterClose=after.slice(3);else{let closeIdx=after.indexOf(`
1322
1322
  ---`);if(closeIdx===-1)return{frontmatter:null,body:content};frontmatter=after.slice(0,closeIdx),afterClose=after.slice(closeIdx+4)}let body=afterClose.startsWith(`
1323
- `)?afterClose.slice(1):afterClose;return{frontmatter,body}}var SdkPermissionModeSchema,SdkEffortLevelSchema,SdkThinkingConfigSchema,SdkMcpStdioServerConfigSchema,SdkMcpSSEServerConfigSchema,SdkMcpHttpServerConfigSchema,SdkMcpServerConfigSchema,SdkSubagentConfigSchema,SdkCustomToolConfigSchema,SdkOutputFormatSchema,SdkPluginConfigSchema,SdkSandboxConfigSchema,SdkHookMatcherConfigSchema,SdkHookEventSchema,SdkBetaSchema,SdkSystemPromptSchema,SdkDirectoryConfigSchema,AgentConfigSchema,DERIVED_KEYS;var init_agent_yaml=__esm(()=>{init_js_yaml();init_zod();init_lockfile();SdkPermissionModeSchema=exports_external.enum(["default","acceptEdits","bypassPermissions","plan","dontAsk","auto","remoteApproval"]),SdkEffortLevelSchema=exports_external.union([exports_external.enum(["low","medium","high","max"]),exports_external.number()]),SdkThinkingConfigSchema=exports_external.union([exports_external.object({type:exports_external.literal("adaptive")}).strict(),exports_external.object({type:exports_external.literal("enabled"),budgetTokens:exports_external.number().optional()}).strict(),exports_external.object({type:exports_external.literal("disabled")}).strict()]),SdkMcpStdioServerConfigSchema=exports_external.object({type:exports_external.literal("stdio").optional(),command:exports_external.string(),args:exports_external.array(exports_external.string()).optional(),env:exports_external.record(exports_external.string()).optional()}).strict(),SdkMcpSSEServerConfigSchema=exports_external.object({type:exports_external.literal("sse"),url:exports_external.string(),headers:exports_external.record(exports_external.string()).optional()}).strict(),SdkMcpHttpServerConfigSchema=exports_external.object({type:exports_external.literal("http"),url:exports_external.string(),headers:exports_external.record(exports_external.string()).optional()}).strict(),SdkMcpServerConfigSchema=exports_external.union([SdkMcpStdioServerConfigSchema,SdkMcpSSEServerConfigSchema,SdkMcpHttpServerConfigSchema]),SdkSubagentConfigSchema=exports_external.object({description:exports_external.string(),prompt:exports_external.string(),tools:exports_external.array(exports_external.string()).optional(),disallowedTools:exports_external.array(exports_external.string()).optional(),model:exports_external.string().optional(),mcpServers:exports_external.array(exports_external.union([exports_external.string(),exports_external.record(SdkMcpStdioServerConfigSchema)])).optional(),skills:exports_external.array(exports_external.string()).optional(),maxTurns:exports_external.number().optional(),background:exports_external.boolean().optional(),memory:exports_external.enum(["user","project","local"]).optional(),effort:SdkEffortLevelSchema.optional(),permissionMode:SdkPermissionModeSchema.optional()}).strict(),SdkCustomToolConfigSchema=exports_external.object({name:exports_external.string(),description:exports_external.string(),inputSchema:exports_external.record(exports_external.unknown()),handler:exports_external.string().optional()}).strict(),SdkOutputFormatSchema=exports_external.object({type:exports_external.literal("json_schema"),schema:exports_external.record(exports_external.unknown())}).strict(),SdkPluginConfigSchema=exports_external.object({type:exports_external.literal("local"),path:exports_external.string()}).strict(),SdkSandboxConfigSchema=exports_external.object({enabled:exports_external.boolean().optional(),autoAllowBashIfSandboxed:exports_external.boolean().optional(),failIfUnavailable:exports_external.boolean().optional(),network:exports_external.object({allowLocalBinding:exports_external.boolean().optional(),allowUnixSockets:exports_external.array(exports_external.string()).optional()}).strict().optional()}).strict(),SdkHookMatcherConfigSchema=exports_external.object({toolName:exports_external.string().optional(),agentName:exports_external.string().optional()}).strict(),SdkHookEventSchema=exports_external.enum(["PreToolUse","PostToolUse","PostToolUseFailure","Notification","UserPromptSubmit","SessionStart","SessionEnd","Stop","StopFailure","SubagentStart","SubagentStop","PreCompact","PostCompact","PermissionRequest","PermissionDenied","Setup","TeammateIdle","TaskCreated","TaskCompleted","Elicitation","ElicitationResult","ConfigChange","WorktreeCreate","WorktreeRemove","InstructionsLoaded","CwdChanged","FileChanged"]),SdkBetaSchema=exports_external.enum(["context-1m-2025-08-07"]),SdkSystemPromptSchema=exports_external.union([exports_external.string(),exports_external.object({type:exports_external.literal("preset"),preset:exports_external.literal("claude_code"),append:exports_external.string().optional()}).strict()]),SdkDirectoryConfigSchema=exports_external.object({permissionMode:SdkPermissionModeSchema.optional(),tools:exports_external.union([exports_external.array(exports_external.string()),exports_external.object({type:exports_external.literal("preset"),preset:exports_external.literal("claude_code")}).strict()]).optional(),allowedTools:exports_external.array(exports_external.string()).optional(),disallowedTools:exports_external.array(exports_external.string()).optional(),maxTurns:exports_external.number().optional(),maxBudgetUsd:exports_external.number().optional(),effort:SdkEffortLevelSchema.optional(),thinking:SdkThinkingConfigSchema.optional(),agent:exports_external.string().optional(),agents:exports_external.record(SdkSubagentConfigSchema).optional(),mcpServers:exports_external.record(SdkMcpServerConfigSchema).optional(),plugins:exports_external.array(SdkPluginConfigSchema).optional(),customTools:exports_external.array(SdkCustomToolConfigSchema).optional(),persistSession:exports_external.boolean().optional(),enableFileCheckpointing:exports_external.boolean().optional(),outputFormat:SdkOutputFormatSchema.optional(),includePartialMessages:exports_external.boolean().optional(),includeHookEvents:exports_external.boolean().optional(),promptSuggestions:exports_external.boolean().optional(),agentProgressSummaries:exports_external.boolean().optional(),systemPrompt:SdkSystemPromptSchema.optional(),sandbox:SdkSandboxConfigSchema.optional(),betas:exports_external.array(SdkBetaSchema).optional(),settingSources:exports_external.array(exports_external.enum(["user","project","local"])).optional(),settings:exports_external.union([exports_external.string(),exports_external.record(exports_external.unknown())]).optional(),hooks:exports_external.record(SdkHookEventSchema,exports_external.array(SdkHookMatcherConfigSchema)).optional()}).strict(),AgentConfigSchema=exports_external.object({name:exports_external.string().optional(),dir:exports_external.string().optional(),repo:exports_external.string().optional(),team:exports_external.string().optional(),promptMode:exports_external.enum(["system","append"]).optional(),model:exports_external.string().optional(),roles:exports_external.array(exports_external.string()).optional(),omniAgentId:exports_external.string().optional(),registeredAt:exports_external.string().optional(),description:exports_external.string().optional(),color:exports_external.string().optional(),provider:exports_external.string().optional(),permissions:exports_external.object({preset:exports_external.string().optional(),allow:exports_external.array(exports_external.string()).optional(),deny:exports_external.array(exports_external.string()).optional(),bashAllowPatterns:exports_external.array(exports_external.string()).optional(),allowedTools:exports_external.array(exports_external.string()).optional(),permissionMode:SdkPermissionModeSchema.optional()}).strict().optional(),disallowedTools:exports_external.array(exports_external.string()).optional(),omniScopes:exports_external.array(exports_external.string()).optional(),hooks:exports_external.record(exports_external.unknown()).optional(),sdk:SdkDirectoryConfigSchema.optional(),bridgeTmuxSession:exports_external.string().optional()}).strict(),DERIVED_KEYS=["name","dir","registeredAt"]});import{existsSync as existsSync37}from"fs";import{copyFile as copyFile2,readFile as readFile6,writeFile as writeFile6}from"fs/promises";import{join as join43}from"path";async function migrateAgentToYaml(agentDir,dbRow){let yamlPath=join43(agentDir,"agent.yaml"),agentsMdPath=join43(agentDir,"AGENTS.md"),bakPath=`${agentsMdPath}.bak`;if(existsSync37(yamlPath))return{migrated:!1,reason:"already-migrated",yamlPath};let agentsMdRaw=await readFile6(agentsMdPath,"utf-8"),{frontmatter,body}=extractFrontmatterFromAgentsMd(agentsMdRaw);if(frontmatter===null)return{migrated:!1,reason:"no-frontmatter",yamlPath};let fmParsed=parseFrontmatter2(frontmatter,agentsMdPath),fmClean=pickYamlFields(fmParsed),merged={...dbRow?pickYamlFields(dbRow):{},...fmClean},config=AgentConfigSchema.parse(merged);return await writeAgentYaml(yamlPath,config),await copyFile2(agentsMdPath,bakPath),await writeFile6(agentsMdPath,body),{migrated:!0,yamlPath,bakPath}}function parseFrontmatter2(frontmatter,sourcePath){let raw;try{raw=load(frontmatter)}catch(err){let msg=err instanceof Error?err.message:String(err);throw Error(`Malformed frontmatter in ${sourcePath}: ${msg}`)}if(raw===null||typeof raw!=="object"||Array.isArray(raw))throw Error(`Malformed frontmatter in ${sourcePath}: expected a YAML mapping at the top level`);return raw}function pickYamlFields(source){let out={};for(let[k,v]of Object.entries(source))if(YAML_ALLOWED_KEYS.has(k)&&v!==null&&v!==void 0)out[k]=v;return out}var YAML_ALLOWED_KEYS;var init_agent_migrate=__esm(()=>{init_js_yaml();init_agent_yaml();YAML_ALLOWED_KEYS=(()=>{let shape=AgentConfigSchema._def.shape(),keys=new Set(Object.keys(shape));return keys.delete("name"),keys.delete("dir"),keys.delete("registeredAt"),keys})()});var exports_agent_sync={};__export(exports_agent_sync,{watchAgentDirectory:()=>watchAgentDirectory,syncSingleAgentByName:()=>syncSingleAgentByName,syncAgentDirectory:()=>syncAgentDirectory,printSyncResult:()=>printSyncResult,healAgentFile:()=>healAgentFile});import{execSync as execSync7}from"child_process";import{existsSync as existsSync38,watch as fsWatch,readFileSync as readFileSync27,readdirSync as readdirSync11,realpathSync as realpathSync5,writeFileSync as writeFileSync16}from"fs";import{join as join44}from"path";function getGitRemoteUrl(dir){try{return execSync7(`git -C "${dir}" config --get remote.origin.url`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function extractOrgRepo(remoteUrl){let sshMatch=remoteUrl.match(/[^/:]+\/[^/]+?(?:\.git)?$/);if(sshMatch)return sshMatch[0].replace(/\.git$/,"");return null}function getRepoPathForAgent(agentDir){let reposLink=join44(agentDir,"repos");try{if(!existsSync38(reposLink))return null;let target=realpathSync5(reposLink);if(!existsSync38(target))return null;return target}catch{return null}}function discoverAgents(workspaceRoot){let agentsDir=join44(workspaceRoot,"agents");if(!existsSync38(agentsDir))return[];let agents=[];try{let entries=readdirSync11(agentsDir,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;let agentDir=join44(agentsDir,entry2.name);if(!existsSync38(join44(agentDir,"AGENTS.md")))continue;agents.push({name:entry2.name,dir:agentDir,repoUrl:getGitRemoteUrl(agentDir),productRepo:getRepoPathForAgent(agentDir)}),discoverSubAgents(agentDir,entry2.name,agents)}}catch{}return agents}function discoverSubAgents(parentDir,parentName,agents){let subAgentsDir=join44(parentDir,".genie","agents");if(!existsSync38(subAgentsDir))return;try{let entries=readdirSync11(subAgentsDir,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;let subDir=join44(subAgentsDir,entry2.name);if(!existsSync38(join44(subDir,"AGENTS.md")))continue;agents.push({name:`${parentName}/${entry2.name}`,dir:subDir,repoUrl:getGitRemoteUrl(parentDir),productRepo:getRepoPathForAgent(parentDir)})}}catch{}}function isSafeAgentName(name){let parts=name.split("/");return parts.length>0&&parts.length<=2&&parts.every((part)=>part!==""&&part!=="."&&part!=="..")}function discoverSingleAgent(workspaceRoot,agentName){if(!isSafeAgentName(agentName))return null;let parts=agentName.split("/");if(parts.length===2){let[parentName,subName]=parts,parentDir=join44(workspaceRoot,"agents",parentName),subDir=join44(parentDir,".genie","agents",subName);if(!existsSync38(join44(subDir,"AGENTS.md")))return null;return{name:agentName,dir:subDir,repoUrl:getGitRemoteUrl(parentDir),productRepo:getRepoPathForAgent(parentDir)}}let agentDir=join44(workspaceRoot,"agents",agentName);if(!existsSync38(join44(agentDir,"AGENTS.md")))return null;return{name:agentName,dir:agentDir,repoUrl:getGitRemoteUrl(agentDir),productRepo:getRepoPathForAgent(agentDir)}}function healAgentFile(agentsMdPath,agentName,healResult){let content=readFileSync27(agentsMdPath,"utf-8"),fmMatch=content.match(/^(---\n)([\s\S]*?)(\n---)/);if(!fmMatch)return!1;let prefix=fmMatch[1],fmBlock=fmMatch[2],suffix=fmMatch[3],rest=content.slice(fmMatch[0].length),modified=!1,healedBlock=fmBlock;for(let{field,value}of INVALID_LITERALS)if(new RegExp(`^${field}:\\s*${value}\\s*$`,"m").test(healedBlock))healedBlock=healedBlock.replace(new RegExp(`${field}:\\s*${value}\\s*\\n?`,"m"),""),healResult.healed.push({agent:agentName,field,value}),modified=!0;if(!modified)return!1;let newContent=prefix+healedBlock+suffix+rest,tmpPath=`${agentsMdPath}.tmp.${Date.now()}`;writeFileSync16(tmpPath,newContent,"utf-8");let{renameSync:renameSync8}=__require("fs");return renameSync8(tmpPath,agentsMdPath),!0}function buildResolveContext(workspaceRoot,agentName){let workspaceDefaults;try{workspaceDefaults=getWorkspaceConfig(workspaceRoot).agents?.defaults}catch{}let parent;if(agentName.includes("/")){let parentName=agentName.split("/")[0],parentAgentsMd=join44(workspaceRoot,"agents",parentName,"AGENTS.md");if(existsSync38(parentAgentsMd)){let parentContent=readFileSync27(parentAgentsMd,"utf-8"),parentFm=parseFrontmatter(parentContent);parent={name:parentName,fields:parentFm}}}return{workspaceDefaults,parent}}function computeResolvedMetadata(fm,ctx){let declared={},resolved={};for(let field of Object.keys(BUILTIN_DEFAULTS)){let fmValue=fm[field];if(fmValue!==void 0&&fmValue!==null&&fmValue!==""&&fmValue!=="inherit")declared[field]=fmValue;let result2=resolveFieldWithSource(fm,field,ctx);resolved[field]={value:result2.value,source:result2.source}}return{declared,resolved}}async function syncAgentDirectory(workspaceRoot){let result2={registered:[],updated:[],migrated:[],archived:[],reactivated:[],healed:[],errors:[]},agents=discoverAgents(workspaceRoot),discoveredNames=new Set(agents.map((a)=>a.name)),healResult={healed:[]};for(let agent of agents){let agentsMdPath=join44(agent.dir,"AGENTS.md");try{healAgentFile(agentsMdPath,agent.name,healResult)}catch{}}result2.healed=healResult.healed;for(let h of healResult.healed)console.log(`[sync] healed ${h.agent}/AGENTS.md: removed invalid '${h.field}: ${h.value}' line`);for(let agent of agents)try{await syncSingleAgent(agent,result2,workspaceRoot)}catch(err){result2.errors.push({name:agent.name,error:err instanceof Error?err.message:String(err)})}return await removeMissingAgents(discoveredNames,result2),result2}function printSyncResult(result2){if(result2.healed.length>0)console.log(` Healed: ${result2.healed.length} invalid literal(s) removed`);if(result2.migrated.length>0)console.log(` Migrated: ${result2.migrated.join(", ")} (AGENTS.md frontmatter \u2192 agent.yaml)`);if(result2.registered.length>0)console.log(` Registered: ${result2.registered.join(", ")}`);if(result2.updated.length>0)console.log(` Updated: ${result2.updated.join(", ")}`);if(result2.reactivated.length>0)console.log(` Reactivated: ${result2.reactivated.join(", ")}`);if(result2.archived.length>0)console.log(` Removed: ${result2.archived.join(", ")}`);for(let err of result2.errors)console.error(` Error (${err.name}): ${err.error}`);let total=result2.registered.length+result2.updated.length+result2.reactivated.length;console.log(`
1323
+ `)?afterClose.slice(1):afterClose;return{frontmatter,body}}var SdkPermissionModeSchema,SdkEffortLevelSchema,SdkThinkingConfigSchema,SdkMcpStdioServerConfigSchema,SdkMcpSSEServerConfigSchema,SdkMcpHttpServerConfigSchema,SdkMcpServerConfigSchema,SdkSubagentConfigSchema,SdkCustomToolConfigSchema,SdkOutputFormatSchema,SdkPluginConfigSchema,SdkSandboxConfigSchema,SdkHookMatcherConfigSchema,SdkHookEventSchema,SdkBetaSchema,SdkSystemPromptSchema,SdkDirectoryConfigSchema,AgentConfigSchema,DERIVED_KEYS;var init_agent_yaml=__esm(()=>{init_js_yaml();init_zod();init_lockfile();SdkPermissionModeSchema=exports_external.enum(["default","acceptEdits","bypassPermissions","plan","dontAsk","auto","remoteApproval"]),SdkEffortLevelSchema=exports_external.union([exports_external.enum(["low","medium","high","max"]),exports_external.number()]),SdkThinkingConfigSchema=exports_external.union([exports_external.object({type:exports_external.literal("adaptive")}).strict(),exports_external.object({type:exports_external.literal("enabled"),budgetTokens:exports_external.number().optional()}).strict(),exports_external.object({type:exports_external.literal("disabled")}).strict()]),SdkMcpStdioServerConfigSchema=exports_external.object({type:exports_external.literal("stdio").optional(),command:exports_external.string(),args:exports_external.array(exports_external.string()).optional(),env:exports_external.record(exports_external.string()).optional()}).strict(),SdkMcpSSEServerConfigSchema=exports_external.object({type:exports_external.literal("sse"),url:exports_external.string(),headers:exports_external.record(exports_external.string()).optional()}).strict(),SdkMcpHttpServerConfigSchema=exports_external.object({type:exports_external.literal("http"),url:exports_external.string(),headers:exports_external.record(exports_external.string()).optional()}).strict(),SdkMcpServerConfigSchema=exports_external.union([SdkMcpStdioServerConfigSchema,SdkMcpSSEServerConfigSchema,SdkMcpHttpServerConfigSchema]),SdkSubagentConfigSchema=exports_external.object({description:exports_external.string(),prompt:exports_external.string(),tools:exports_external.array(exports_external.string()).optional(),disallowedTools:exports_external.array(exports_external.string()).optional(),model:exports_external.string().optional(),mcpServers:exports_external.array(exports_external.union([exports_external.string(),exports_external.record(SdkMcpStdioServerConfigSchema)])).optional(),skills:exports_external.array(exports_external.string()).optional(),maxTurns:exports_external.number().optional(),background:exports_external.boolean().optional(),memory:exports_external.enum(["user","project","local"]).optional(),effort:SdkEffortLevelSchema.optional(),permissionMode:SdkPermissionModeSchema.optional()}).strict(),SdkCustomToolConfigSchema=exports_external.object({name:exports_external.string(),description:exports_external.string(),inputSchema:exports_external.record(exports_external.unknown()),handler:exports_external.string().optional()}).strict(),SdkOutputFormatSchema=exports_external.object({type:exports_external.literal("json_schema"),schema:exports_external.record(exports_external.unknown())}).strict(),SdkPluginConfigSchema=exports_external.object({type:exports_external.literal("local"),path:exports_external.string()}).strict(),SdkSandboxConfigSchema=exports_external.object({enabled:exports_external.boolean().optional(),autoAllowBashIfSandboxed:exports_external.boolean().optional(),failIfUnavailable:exports_external.boolean().optional(),network:exports_external.object({allowLocalBinding:exports_external.boolean().optional(),allowUnixSockets:exports_external.array(exports_external.string()).optional()}).strict().optional()}).strict(),SdkHookMatcherConfigSchema=exports_external.object({toolName:exports_external.string().optional(),agentName:exports_external.string().optional()}).strict(),SdkHookEventSchema=exports_external.enum(["PreToolUse","PostToolUse","PostToolUseFailure","Notification","UserPromptSubmit","SessionStart","SessionEnd","Stop","StopFailure","SubagentStart","SubagentStop","PreCompact","PostCompact","PermissionRequest","PermissionDenied","Setup","TeammateIdle","TaskCreated","TaskCompleted","Elicitation","ElicitationResult","ConfigChange","WorktreeCreate","WorktreeRemove","InstructionsLoaded","CwdChanged","FileChanged"]),SdkBetaSchema=exports_external.enum(["context-1m-2025-08-07"]),SdkSystemPromptSchema=exports_external.union([exports_external.string(),exports_external.object({type:exports_external.literal("preset"),preset:exports_external.literal("claude_code"),append:exports_external.string().optional()}).strict()]),SdkDirectoryConfigSchema=exports_external.object({permissionMode:SdkPermissionModeSchema.optional(),tools:exports_external.union([exports_external.array(exports_external.string()),exports_external.object({type:exports_external.literal("preset"),preset:exports_external.literal("claude_code")}).strict()]).optional(),allowedTools:exports_external.array(exports_external.string()).optional(),disallowedTools:exports_external.array(exports_external.string()).optional(),maxTurns:exports_external.number().optional(),maxBudgetUsd:exports_external.number().optional(),effort:SdkEffortLevelSchema.optional(),thinking:SdkThinkingConfigSchema.optional(),agent:exports_external.string().optional(),agents:exports_external.record(SdkSubagentConfigSchema).optional(),mcpServers:exports_external.record(SdkMcpServerConfigSchema).optional(),plugins:exports_external.array(SdkPluginConfigSchema).optional(),customTools:exports_external.array(SdkCustomToolConfigSchema).optional(),persistSession:exports_external.boolean().optional(),enableFileCheckpointing:exports_external.boolean().optional(),outputFormat:SdkOutputFormatSchema.optional(),includePartialMessages:exports_external.boolean().optional(),includeHookEvents:exports_external.boolean().optional(),promptSuggestions:exports_external.boolean().optional(),agentProgressSummaries:exports_external.boolean().optional(),systemPrompt:SdkSystemPromptSchema.optional(),sandbox:SdkSandboxConfigSchema.optional(),betas:exports_external.array(SdkBetaSchema).optional(),settingSources:exports_external.array(exports_external.enum(["user","project","local"])).optional(),settings:exports_external.union([exports_external.string(),exports_external.record(exports_external.unknown())]).optional(),hooks:exports_external.record(SdkHookEventSchema,exports_external.array(SdkHookMatcherConfigSchema)).optional()}).strict(),AgentConfigSchema=exports_external.object({name:exports_external.string().optional(),dir:exports_external.string().optional(),repo:exports_external.string().optional(),team:exports_external.string().optional(),promptMode:exports_external.enum(["system","append"]).optional(),model:exports_external.string().optional(),roles:exports_external.array(exports_external.string()).optional(),omniAgentId:exports_external.string().optional(),registeredAt:exports_external.string().optional(),description:exports_external.string().optional(),color:exports_external.string().optional(),provider:exports_external.string().optional(),permissions:exports_external.object({preset:exports_external.string().optional(),allow:exports_external.array(exports_external.string()).optional(),deny:exports_external.array(exports_external.string()).optional(),bashAllowPatterns:exports_external.array(exports_external.string()).optional(),allowedTools:exports_external.array(exports_external.string()).optional(),permissionMode:SdkPermissionModeSchema.optional()}).strict().optional(),disallowedTools:exports_external.array(exports_external.string()).optional(),omniScopes:exports_external.array(exports_external.string()).optional(),hooks:exports_external.record(exports_external.unknown()).optional(),sdk:SdkDirectoryConfigSchema.optional(),bridgeTmuxSession:exports_external.string().optional()}).strict(),DERIVED_KEYS=["name","dir","registeredAt"]});import{existsSync as existsSync37}from"fs";import{copyFile,readFile as readFile6,writeFile as writeFile6}from"fs/promises";import{join as join43}from"path";async function migrateAgentToYaml(agentDir,dbRow){let yamlPath=join43(agentDir,"agent.yaml"),agentsMdPath=join43(agentDir,"AGENTS.md"),bakPath=`${agentsMdPath}.bak`;if(existsSync37(yamlPath))return{migrated:!1,reason:"already-migrated",yamlPath};let agentsMdRaw=await readFile6(agentsMdPath,"utf-8"),{frontmatter,body}=extractFrontmatterFromAgentsMd(agentsMdRaw);if(frontmatter===null)return{migrated:!1,reason:"no-frontmatter",yamlPath};let fmParsed=parseFrontmatter2(frontmatter,agentsMdPath),fmClean=pickYamlFields(fmParsed),merged={...dbRow?pickYamlFields(dbRow):{},...fmClean},config=AgentConfigSchema.parse(merged);return await writeAgentYaml(yamlPath,config),await copyFile(agentsMdPath,bakPath),await writeFile6(agentsMdPath,body),{migrated:!0,yamlPath,bakPath}}function parseFrontmatter2(frontmatter,sourcePath){let raw;try{raw=load(frontmatter)}catch(err){let msg=err instanceof Error?err.message:String(err);throw Error(`Malformed frontmatter in ${sourcePath}: ${msg}`)}if(raw===null||typeof raw!=="object"||Array.isArray(raw))throw Error(`Malformed frontmatter in ${sourcePath}: expected a YAML mapping at the top level`);return raw}function pickYamlFields(source){let out={};for(let[k,v]of Object.entries(source))if(YAML_ALLOWED_KEYS.has(k)&&v!==null&&v!==void 0)out[k]=v;return out}var YAML_ALLOWED_KEYS;var init_agent_migrate=__esm(()=>{init_js_yaml();init_agent_yaml();YAML_ALLOWED_KEYS=(()=>{let shape=AgentConfigSchema._def.shape(),keys=new Set(Object.keys(shape));return keys.delete("name"),keys.delete("dir"),keys.delete("registeredAt"),keys})()});var exports_agent_sync={};__export(exports_agent_sync,{watchAgentDirectory:()=>watchAgentDirectory,syncSingleAgentByName:()=>syncSingleAgentByName,syncAgentDirectory:()=>syncAgentDirectory,printSyncResult:()=>printSyncResult,healAgentFile:()=>healAgentFile});import{execSync as execSync7}from"child_process";import{existsSync as existsSync38,watch as fsWatch,readFileSync as readFileSync27,readdirSync as readdirSync11,realpathSync as realpathSync6,writeFileSync as writeFileSync16}from"fs";import{join as join44}from"path";function getGitRemoteUrl(dir){try{return execSync7(`git -C "${dir}" config --get remote.origin.url`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function extractOrgRepo(remoteUrl){let sshMatch=remoteUrl.match(/[^/:]+\/[^/]+?(?:\.git)?$/);if(sshMatch)return sshMatch[0].replace(/\.git$/,"");return null}function getRepoPathForAgent(agentDir){let reposLink=join44(agentDir,"repos");try{if(!existsSync38(reposLink))return null;let target=realpathSync6(reposLink);if(!existsSync38(target))return null;return target}catch{return null}}function discoverAgents(workspaceRoot){let agentsDir=join44(workspaceRoot,"agents");if(!existsSync38(agentsDir))return[];let agents=[];try{let entries=readdirSync11(agentsDir,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;let agentDir=join44(agentsDir,entry2.name);if(!existsSync38(join44(agentDir,"AGENTS.md")))continue;agents.push({name:entry2.name,dir:agentDir,repoUrl:getGitRemoteUrl(agentDir),productRepo:getRepoPathForAgent(agentDir)}),discoverSubAgents(agentDir,entry2.name,agents)}}catch{}return agents}function discoverSubAgents(parentDir,parentName,agents){let subAgentsDir=join44(parentDir,".genie","agents");if(!existsSync38(subAgentsDir))return;try{let entries=readdirSync11(subAgentsDir,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;let subDir=join44(subAgentsDir,entry2.name);if(!existsSync38(join44(subDir,"AGENTS.md")))continue;agents.push({name:`${parentName}/${entry2.name}`,dir:subDir,repoUrl:getGitRemoteUrl(parentDir),productRepo:getRepoPathForAgent(parentDir)})}}catch{}}function isSafeAgentName(name){let parts=name.split("/");return parts.length>0&&parts.length<=2&&parts.every((part)=>part!==""&&part!=="."&&part!=="..")}function discoverSingleAgent(workspaceRoot,agentName){if(!isSafeAgentName(agentName))return null;let parts=agentName.split("/");if(parts.length===2){let[parentName,subName]=parts,parentDir=join44(workspaceRoot,"agents",parentName),subDir=join44(parentDir,".genie","agents",subName);if(!existsSync38(join44(subDir,"AGENTS.md")))return null;return{name:agentName,dir:subDir,repoUrl:getGitRemoteUrl(parentDir),productRepo:getRepoPathForAgent(parentDir)}}let agentDir=join44(workspaceRoot,"agents",agentName);if(!existsSync38(join44(agentDir,"AGENTS.md")))return null;return{name:agentName,dir:agentDir,repoUrl:getGitRemoteUrl(agentDir),productRepo:getRepoPathForAgent(agentDir)}}function healAgentFile(agentsMdPath,agentName,healResult){let content=readFileSync27(agentsMdPath,"utf-8"),fmMatch=content.match(/^(---\n)([\s\S]*?)(\n---)/);if(!fmMatch)return!1;let prefix=fmMatch[1],fmBlock=fmMatch[2],suffix=fmMatch[3],rest=content.slice(fmMatch[0].length),modified=!1,healedBlock=fmBlock;for(let{field,value}of INVALID_LITERALS)if(new RegExp(`^${field}:\\s*${value}\\s*$`,"m").test(healedBlock))healedBlock=healedBlock.replace(new RegExp(`${field}:\\s*${value}\\s*\\n?`,"m"),""),healResult.healed.push({agent:agentName,field,value}),modified=!0;if(!modified)return!1;let newContent=prefix+healedBlock+suffix+rest,tmpPath=`${agentsMdPath}.tmp.${Date.now()}`;writeFileSync16(tmpPath,newContent,"utf-8");let{renameSync:renameSync9}=__require("fs");return renameSync9(tmpPath,agentsMdPath),!0}function buildResolveContext(workspaceRoot,agentName){let workspaceDefaults;try{workspaceDefaults=getWorkspaceConfig(workspaceRoot).agents?.defaults}catch{}let parent;if(agentName.includes("/")){let parentName=agentName.split("/")[0],parentAgentsMd=join44(workspaceRoot,"agents",parentName,"AGENTS.md");if(existsSync38(parentAgentsMd)){let parentContent=readFileSync27(parentAgentsMd,"utf-8"),parentFm=parseFrontmatter(parentContent);parent={name:parentName,fields:parentFm}}}return{workspaceDefaults,parent}}function computeResolvedMetadata(fm,ctx){let declared={},resolved={};for(let field of Object.keys(BUILTIN_DEFAULTS)){let fmValue=fm[field];if(fmValue!==void 0&&fmValue!==null&&fmValue!==""&&fmValue!=="inherit")declared[field]=fmValue;let result2=resolveFieldWithSource(fm,field,ctx);resolved[field]={value:result2.value,source:result2.source}}return{declared,resolved}}async function syncAgentDirectory(workspaceRoot){let result2={registered:[],updated:[],migrated:[],archived:[],reactivated:[],healed:[],errors:[]},agents=discoverAgents(workspaceRoot),discoveredNames=new Set(agents.map((a)=>a.name)),healResult={healed:[]};for(let agent of agents){let agentsMdPath=join44(agent.dir,"AGENTS.md");try{healAgentFile(agentsMdPath,agent.name,healResult)}catch{}}result2.healed=healResult.healed;for(let h of healResult.healed)console.log(`[sync] healed ${h.agent}/AGENTS.md: removed invalid '${h.field}: ${h.value}' line`);for(let agent of agents)try{await syncSingleAgent(agent,result2,workspaceRoot)}catch(err){result2.errors.push({name:agent.name,error:err instanceof Error?err.message:String(err)})}return await removeMissingAgents(discoveredNames,result2),result2}function printSyncResult(result2){if(result2.healed.length>0)console.log(` Healed: ${result2.healed.length} invalid literal(s) removed`);if(result2.migrated.length>0)console.log(` Migrated: ${result2.migrated.join(", ")} (AGENTS.md frontmatter \u2192 agent.yaml)`);if(result2.registered.length>0)console.log(` Registered: ${result2.registered.join(", ")}`);if(result2.updated.length>0)console.log(` Updated: ${result2.updated.join(", ")}`);if(result2.reactivated.length>0)console.log(` Reactivated: ${result2.reactivated.join(", ")}`);if(result2.archived.length>0)console.log(` Removed: ${result2.archived.join(", ")}`);for(let err of result2.errors)console.error(` Error (${err.name}): ${err.error}`);let total=result2.registered.length+result2.updated.length+result2.reactivated.length;console.log(`
1324
1324
  Synced: ${total} agent(s), ${result2.archived.length} removed.`)}async function removeMissingAgents(discoveredNames,result2){try{let entries=await ls();for(let entry2 of entries){if(discoveredNames.has(entry2.name))continue;if(entry2.scope==="built-in")continue;if(!entry2.dir||!entry2.dir.includes("/agents/"))continue;let{removed}=await rm2(entry2.name);if(removed)result2.archived.push(entry2.name)}}catch{}}async function maybeMigrateFrontmatter(agent,result2){let yamlPath=join44(agent.dir,"agent.yaml"),agentsMdPath=join44(agent.dir,"AGENTS.md");if(existsSync38(yamlPath)||!existsSync38(agentsMdPath))return;let{frontmatter}=extractFrontmatterFromAgentsMd(readFileSync27(agentsMdPath,"utf-8"));if(frontmatter===null)return;let existingEntry=await resolve7(agent.name),dbRow=existingEntry&&!existingEntry.builtin?dbRowFromEntry(existingEntry.entry):void 0;if((await migrateAgentToYaml(agent.dir,dbRow)).migrated)result2.migrated.push(agent.name)}function buildDirectoryPayload(dir,repoPath,cf){return{dir,repo:repoPath,promptMode:cf.promptMode,model:cf.model,description:cf.description,color:cf.color,provider:cf.provider,roles:cf.roles,permissions:cf.permissions,disallowedTools:cf.disallowedTools,omniScopes:cf.omniScopes,hooks:cf.hooks,sdk:cf.sdk,bridgeTmuxSession:cf.bridgeTmuxSession}}async function syncSingleAgent(agent,result2,workspaceRoot){let repoPath=(agent.repoUrl?extractOrgRepo(agent.repoUrl):null)??agent.repoUrl??agent.dir,yamlPath=join44(agent.dir,"agent.yaml"),agentsMdPath=join44(agent.dir,"AGENTS.md");await maybeMigrateFrontmatter(agent,result2);let configFields=existsSync38(yamlPath)?await readYamlAsConfigFields(yamlPath):readFrontmatterAsConfigFields(agentsMdPath);if(workspaceRoot){let ctx=buildResolveContext(workspaceRoot,agent.name);computeResolvedMetadata(configFields.rawForResolution,ctx)}let resolved=await resolve7(agent.name),existing=resolved&&!resolved.builtin?resolved.entry:null,payload=buildDirectoryPayload(agent.dir,repoPath,configFields);if(!existing){await add({name:agent.name,...payload}),result2.registered.push(agent.name);return}await edit(agent.name,payload),result2.updated.push(agent.name)}async function readYamlAsConfigFields(yamlPath){let cfg=await parseAgentYaml(yamlPath);return{promptMode:cfg.promptMode??"append",model:cfg.model,description:cfg.description,color:cfg.color,provider:cfg.provider,roles:cfg.roles,permissions:cfg.permissions,disallowedTools:cfg.disallowedTools,omniScopes:cfg.omniScopes,hooks:cfg.hooks,sdk:cfg.sdk,bridgeTmuxSession:cfg.bridgeTmuxSession,rawForResolution:cfg}}function readFrontmatterAsConfigFields(agentsMdPath){let content=existsSync38(agentsMdPath)?readFileSync27(agentsMdPath,"utf-8"):"",fm=parseFrontmatter(content);return{promptMode:fm.promptMode??"append",model:fm.model,description:fm.description,color:fm.color,provider:fm.provider,roles:fm.roles,permissions:fm.permissions,disallowedTools:fm.disallowedTools,omniScopes:fm.omniScopes,hooks:fm.hooks,sdk:fm.sdk,bridgeTmuxSession:fm.bridgeTmuxSession,rawForResolution:fm}}function dbRowFromEntry(entry2){return{team:entry2.team,model:entry2.model,description:entry2.description,color:entry2.color,provider:entry2.provider,promptMode:entry2.promptMode,permissions:entry2.permissions,disallowedTools:entry2.disallowedTools,omniScopes:entry2.omniScopes,hooks:entry2.hooks,sdk:entry2.sdk,bridgeTmuxSession:entry2.bridgeTmuxSession}}async function syncSingleAgentByName(workspaceRoot,agentName){let agent=discoverSingleAgent(workspaceRoot,agentName);if(!agent)return"not-found";let result2={registered:[],updated:[],migrated:[],archived:[],reactivated:[],healed:[],errors:[]};if(await syncSingleAgent(agent,result2,workspaceRoot),result2.registered.length>0)return"registered";if(result2.migrated.length>0)return"migrated";if(result2.updated.length>0)return"updated";return"synced"}function watchAgentDirectory(workspaceRoot,options){let agentsDir=join44(workspaceRoot,"agents");if(!existsSync38(agentsDir))return null;let debounceTimer=null,pendingChanges=new Set,processChanges=async()=>{let names=[...pendingChanges];pendingChanges.clear();for(let name of names)try{let action=await processWatchedAgent(workspaceRoot,agentsDir,name);if(action)options?.onSync?.(name,action)}catch{}},watcher=fsWatch(agentsDir,{persistent:!1},(_event,filename)=>{if(!filename)return;let name=filename.split("/")[0];if(!name||name.startsWith("."))return;if(pendingChanges.add(name),debounceTimer)clearTimeout(debounceTimer);debounceTimer=setTimeout(processChanges,2000)});return{close:()=>{if(debounceTimer)clearTimeout(debounceTimer);watcher.close()}}}async function processWatchedAgent(workspaceRoot,agentsDir,name){let agentDir=join44(agentsDir,name);if(existsSync38(agentDir)&&existsSync38(join44(agentDir,"AGENTS.md"))){let action=await syncSingleAgentByName(workspaceRoot,name);return action!=="synced"&&action!=="not-found"?action:null}if(!existsSync38(agentDir)){let{removed}=await rm2(name);if(removed)return"removed"}return null}var INVALID_LITERALS;var init_agent_sync=__esm(()=>{init_agent_directory();init_agent_migrate();init_agent_yaml();init_defaults();init_frontmatter();init_workspace();INVALID_LITERALS=[{field:"model",value:"inherit"}]});var exports_term_format={};__export(exports_term_format,{truncate:()=>truncate2,stripAnsi:()=>stripAnsi2,padRight:()=>padRight,formatTimestamp:()=>formatTimestamp,formatTime:()=>formatTime,formatRelativeTimestamp:()=>formatRelativeTimestamp,formatDate:()=>formatDate,color:()=>color});function padRight(str2,len){return str2.length>=len?str2:str2+" ".repeat(len-str2.length)}function truncate2(str2,len){return str2.length<=len?str2:`${str2.slice(0,len-1)}\u2026`}function formatDate(iso){if(!iso)return"-";return new Date(iso).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function formatRelativeTimestamp(ts3){let d=new Date(ts3),diffMs=Date.now()-d.getTime();if(diffMs<60000)return`${Math.floor(diffMs/1000)}s ago`;if(diffMs<3600000)return`${Math.floor(diffMs/60000)}m ago`;if(diffMs<86400000)return`${Math.floor(diffMs/3600000)}h ago`;return d.toISOString().replace("T"," ").slice(0,19)}function formatTimestamp(iso,opts){if(!iso)return opts?.fallback??"-";let d=iso instanceof Date?iso:new Date(iso),fmt={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1};if(opts?.seconds)fmt.second="2-digit";return d.toLocaleString("en-US",fmt)}function formatTime(iso,opts){try{let date=new Date(iso),fmt={hour:"2-digit",minute:"2-digit",hour12:!1};if(opts?.seconds)fmt.second="2-digit";return date.toLocaleTimeString("en-US",fmt)}catch{return opts?.fallback??"??:??"}}function color(name,text){return isTTY?`${ANSI[name]}${text}${ANSI.reset}`:text}function stripAnsi2(str2){return str2.replace(ANSI_REGEX,"")}var ANSI,isTTY,ANSI_REGEX;var init_term_format=__esm(()=>{ANSI={reset:"\x1B[0m",dim:"\x1B[2m",bold:"\x1B[1m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",gray:"\x1B[90m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightCyan:"\x1B[96m"},isTTY=process.stdout.isTTY&&!process.env.NO_COLOR;ANSI_REGEX=/\x1b\[[0-9;]*m/g});var exports_task_service={};__export(exports_task_service,{updateTask:()=>updateTask,updateMessage:()=>updateMessage,untagTask:()=>untagTask,unblockTask:()=>unblockTask,unarchiveTask:()=>unarchiveTask,unarchiveProject:()=>unarchiveProject,tagTask:()=>tagTask,setRelease:()=>setRelease,setPreference:()=>setPreference,sendMessage:()=>sendMessage,resolveTaskId:()=>resolveTaskId,resolveChannels:()=>resolveChannels,removeMember:()=>removeMember,removeDependency:()=>removeDependency,removeActor:()=>removeActor,releaseTask:()=>releaseTask,moveTask:()=>moveTask,markDone:()=>markDone,listTypes:()=>listTypes,listTasksForActor:()=>listTasksForActor,listTasks:()=>listTasks,listTags:()=>listTags,listReleases:()=>listReleases,listProjectsFiltered:()=>listProjectsFiltered,listProjects:()=>listProjects,listConversations:()=>listConversations,linkTask:()=>linkTask,getType:()=>getType,getTaskTags:()=>getTaskTags,getTaskActors:()=>getTaskActors,getTask:()=>getTask,getStageLog:()=>getStageLog,getProjectByRepoPath:()=>getProjectByRepoPath,getProjectByName:()=>getProjectByName,getPreferences:()=>getPreferences,getMessages:()=>getMessages,getMessage:()=>getMessage,getMembers:()=>getMembers,getDependents:()=>getDependents,getConversation:()=>getConversation,getCheckoutOwner:()=>getCheckoutOwner,getBlockingDependencies:()=>getBlockingDependencies,getBlockers:()=>getBlockers,forceUnlockTask:()=>forceUnlockTask,findOrCreateConversation:()=>findOrCreateConversation,expireStaleCheckouts:()=>expireStaleCheckouts,ensureProject:()=>ensureProject,deletePreference:()=>deletePreference,createType:()=>createType,createTask:()=>createTask,createTag:()=>createTag,createProject:()=>createProject,commentOnTask:()=>commentOnTask,checkoutTask:()=>checkoutTask,blockTask:()=>blockTask,assignTask:()=>assignTask,archiveTask:()=>archiveTask,archiveProject:()=>archiveProject,archiveBoard:()=>archiveBoard,addMember:()=>addMember,addDependency:()=>addDependency});import{execSync as execSync8}from"child_process";function str2(v){return v!=null?String(v):null}function strOrDefault(v,def){return v!=null?String(v):def}function mapTask(row){return{id:row.id,seq:row.seq,parentId:str2(row.parent_id),repoPath:row.repo_path,projectId:str2(row.project_id),genieOsFolderId:str2(row.genie_os_folder_id),wishFile:str2(row.wish_file),groupName:str2(row.group_name),title:row.title,description:str2(row.description),acceptanceCriteria:str2(row.acceptance_criteria),typeId:row.type_id,stage:row.stage,status:row.status,priority:row.priority,startDate:str2(row.start_date),dueDate:str2(row.due_date),estimatedEffort:str2(row.estimated_effort),startedAt:str2(row.started_at),endedAt:str2(row.ended_at),blockedReason:str2(row.blocked_reason),releaseId:str2(row.release_id),checkoutRunId:str2(row.checkout_run_id),executionLockedAt:str2(row.execution_locked_at),checkoutTimeoutMs:row.checkout_timeout_ms??600000,sessionId:str2(row.session_id),paneId:str2(row.pane_id),traceId:str2(row.trace_id),boardId:str2(row.board_id),columnId:str2(row.column_id),externalId:str2(row.external_id),externalUrl:str2(row.external_url),archivedAt:str2(row.archived_at),metadata:row.metadata??{},createdAt:strOrDefault(row.created_at,""),updatedAt:strOrDefault(row.updated_at,"")}}function mapConversation(row){return{id:row.id,parentMessageId:row.parent_message_id!=null?Number(row.parent_message_id):null,name:row.name??null,type:row.type,linkedEntity:row.linked_entity??null,linkedEntityId:row.linked_entity_id??null,createdByType:row.created_by_type??null,createdById:row.created_by_id??null,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapMessage(row){return{id:Number(row.id),conversationId:row.conversation_id,replyToId:row.reply_to_id!=null?Number(row.reply_to_id):null,senderType:row.sender_type,senderId:row.sender_id,body:row.body,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapTaskActor(row){return{taskId:row.task_id,actorType:row.actor_type,actorId:row.actor_id,role:row.role,permissions:row.permissions??{},createdAt:String(row.created_at)}}function mapDependency(row){return{taskId:row.task_id,dependsOnId:row.depends_on_id,depType:row.dep_type,createdAt:String(row.created_at)}}function mapTag(row){return{id:row.id,name:row.name,color:row.color??palette.textDim,typeId:row.type_id??null,createdAt:String(row.created_at)}}function mapTaskType(row){return{id:row.id,name:row.name,description:row.description??null,icon:row.icon??null,stages:row.stages,isBuiltin:row.is_builtin,createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapNotificationPref(row){return{actorType:row.actor_type,actorId:row.actor_id,channel:row.channel,priorityThreshold:row.priority_threshold,isDefault:row.is_default,enabled:row.enabled,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapStageLog(row){return{id:Number(row.id),taskId:row.task_id,fromStage:row.from_stage??null,toStage:row.to_stage,actorType:row.actor_type??null,actorId:row.actor_id??null,runId:row.run_id??null,gateType:row.gate_type??null,createdAt:String(row.created_at)}}function mapConversationMember(row){return{conversationId:row.conversation_id,actorType:row.actor_type,actorId:row.actor_id,role:row.role,joinedAt:String(row.joined_at)}}function mapProject(row){return{id:row.id,name:row.name,repoPath:str2(row.repo_path),description:str2(row.description),leaderAgent:str2(row.leader_agent),tmuxSession:str2(row.tmux_session),status:strOrDefault(row.status,"active"),archivedAt:str2(row.archived_at),createdAt:String(row.created_at)}}function getRepoPath(){try{return execSync8("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}async function resolveTaskId(idOrSeq,repoPath){let sql=await getConnection(),repo=repoPath??getRepoPath(),projectSeqMatch=idOrSeq.match(/^([^#]+)#(\d+)$/);if(projectSeqMatch&&!idOrSeq.startsWith("#")){let[,projectName,seqStr]=projectSeqMatch,seq2=Number.parseInt(seqStr,10);if(Number.isNaN(seq2))return null;let rows2=await sql`
1325
1325
  SELECT t.id FROM tasks t
1326
1326
  JOIN projects p ON t.project_id = p.id
@@ -1694,7 +1694,7 @@ Stopping inbox watcher...`),stopInboxWatcher2(handle),process.exit(0)};process.o
1694
1694
  SELECT decision, timeout_at FROM approvals WHERE id = ${approvalId}
1695
1695
  `;if(!approval)return"deny";if(approval.decision==="allow"||approval.decision==="deny")return approval.decision;if(new Date(approval.timeout_at)<=new Date)return await resolveApproval(approvalId,defaultAction,"timeout"),defaultAction;return null}async function waitForResolution(approvalId,timeoutAt,defaultAction){let sql=await getConnection();return new Promise((resolve8)=>{let resolved=!1,listener=null,pollTimer=null,finish=(decision)=>{if(resolved)return;if(resolved=!0,listener)listener.unlisten().catch(()=>{});if(pollTimer)clearInterval(pollTimer);resolve8(decision)},checkResolution=async()=>{if(resolved)return;try{let result2=await pollApprovalState(approvalId,defaultAction);if(result2!==null)finish(result2)}catch{finish("deny")}};sql.listen("genie_approval_resolved",(payload)=>{if(payload===approvalId)checkResolution()}).then((l)=>{if(listener=l,resolved)l.unlisten().catch(()=>{})}).catch(()=>{}),pollTimer=setInterval(checkResolution,5000);let msUntilTimeout=Math.max(0,timeoutAt.getTime()-Date.now()+1000);setTimeout(()=>{if(!resolved)resolveApproval(approvalId,defaultAction,"timeout").catch(()=>{}),finish(defaultAction)},msUntilTimeout).unref(),checkResolution()})}function createRemoteApprovalGate(config){let timeoutSec=config.permissions?.timeout??300,defaultAction=config.permissions?.defaultAction??"deny";return async(input)=>{let hookInput=input,toolName=hookInput.tool_name,toolInput=hookInput.tool_input??{},preview=JSON.stringify(toolInput).slice(0,500),timeoutAt=new Date(Date.now()+timeoutSec*1000),approvalId=await insertApproval(config.executorId,config.agentName,toolName,preview,timeoutAt);if(config.permissions?.omniChat&&config.permissions?.omniInstance)sendApprovalToOmni(approvalId,config.agentName,toolName,preview,config.permissions).catch(()=>{});return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:await waitForResolution(approvalId,timeoutAt,defaultAction)}}}}var recentOmniSends,BATCH_WINDOW_MS=1e4,BATCH_THRESHOLD=3;var init_claude_sdk_remote_approval=__esm(()=>{init_db();recentOmniSends=[]});var exports_claude_sdk={};__export(exports_claude_sdk,{translateSdkConfig:()=>translateSdkConfig,ClaudeSdkProvider:()=>ClaudeSdkProvider});import{readFileSync as readFileSync28}from"fs";import{query}from"@anthropic-ai/claude-agent-sdk";function translateSdkConfig(sdkConfig){let opts={};for(let key of SDK_TRUTHY_FIELDS)if(sdkConfig[key])opts[key]=sdkConfig[key];for(let key of SDK_NULLABLE_FIELDS)if(sdkConfig[key]!=null)opts[key]=sdkConfig[key];for(let key of SDK_CAST_FIELDS)if(sdkConfig[key])opts[key]=sdkConfig[key];return opts}function mergeHooks(...sources){let merged={};for(let src of sources){if(!src)continue;for(let[event,matchers]of Object.entries(src)){if(!matchers)continue;if(!merged[event])merged[event]=[...matchers];else merged[event].push(...matchers)}}return merged}class ClaudeSdkProvider{name="claude-sdk";transport="process";activeQueries=new Map;buildSpawnCommand(ctx){return{command:"claude-sdk-in-process",provider:"claude-sdk",meta:{role:ctx.role,skill:ctx.skill}}}runQuery(ctx,prompt2,permissionConfig,extraOptions,sdkConfig){ensureClaudeSettingsSafe();let abortController=new AbortController,tracker={abortController,done:!1};this.activeQueries.set(ctx.executorId,tracker);let permHooks;if(sdkConfig?.permissionMode==="remoteApproval"){let ws=findWorkspace(ctx.cwd),permissions=ws?getWorkspaceConfig(ws.root).permissions:void 0;permHooks={PreToolUse:[{matcher:"*",hooks:[createRemoteApprovalGate({executorId:ctx.executorId,agentName:ctx.agentId??ctx.role??"unknown",permissions})]}]}}else if(permissionConfig)permHooks={PreToolUse:[{matcher:"*",hooks:[createPermissionGate(permissionConfig)]}]};let translatedSdk=sdkConfig?translateSdkConfig(sdkConfig):void 0,mergedHooks=mergeHooks(permHooks,translatedSdk?.hooks,extraOptions?.hooks),hasHooks=Object.keys(mergedHooks).length>0,resolvedSystemPrompt=ctx.systemPrompt;if(!resolvedSystemPrompt&&ctx.systemPromptFile)try{resolvedSystemPrompt=readFileSync28(ctx.systemPromptFile,"utf-8")}catch{}let options={cwd:ctx.cwd,abortController,...ctx.model&&{model:ctx.model},...resolvedSystemPrompt&&{systemPrompt:resolvedSystemPrompt},includePartialMessages:!0,agentProgressSummaries:!0,...translatedSdk,...extraOptions,...hasHooks&&{hooks:mergedHooks},permissionMode:"auto",allowDangerouslySkipPermissions:!0},messages2=query({prompt:prompt2,options}),originalReturn=messages2.return.bind(messages2);messages2.return=async(value)=>{return tracker.done=!0,this.activeQueries.delete(ctx.executorId),originalReturn(value)};let self2=this,wrappedMessages=async function*(){try{for await(let msg of messages2)yield msg,routeSdkMessage(msg,ctx.executorId,ctx.agentId).catch(()=>{})}finally{tracker.done=!0,self2.activeQueries.delete(ctx.executorId)}}();return wrappedMessages.interrupt=messages2.interrupt.bind(messages2),wrappedMessages.setPermissionMode=messages2.setPermissionMode.bind(messages2),wrappedMessages.setModel=messages2.setModel.bind(messages2),wrappedMessages.return=messages2.return.bind(messages2),wrappedMessages.throw=messages2.throw.bind(messages2),{messages:wrappedMessages,abortController}}async extractSession(executor){let sessionId=executor.claudeSessionId;if(!sessionId)return null;return{sessionId}}async detectState(executor){let tracker=this.activeQueries.get(executor.id);if(!tracker)return"done";return tracker.done?"done":"running"}async terminate(executor){let tracker=this.activeQueries.get(executor.id);if(tracker)tracker.abortController.abort(),tracker.done=!0,this.activeQueries.delete(executor.id)}canResume(){return!1}}var SDK_TRUTHY_FIELDS,SDK_NULLABLE_FIELDS,SDK_CAST_FIELDS;var init_claude_sdk=__esm(()=>{init_claude_settings();init_workspace();init_claude_sdk_events();init_claude_sdk_permissions();init_claude_sdk_remote_approval();SDK_TRUTHY_FIELDS=["tools","allowedTools","disallowedTools","plugins","systemPrompt","betas","settingSources"],SDK_NULLABLE_FIELDS=["maxTurns","maxBudgetUsd","persistSession","enableFileCheckpointing","includePartialMessages","includeHookEvents","promptSuggestions","agentProgressSummaries"],SDK_CAST_FIELDS=["effort","thinking","agents","mcpServers","outputFormat","sandbox","settings"]});function detectCodexState(output){if(!output||!output.trim())return{type:"unknown",detail:"empty pane"};let tail=output.split(`
1696
1696
  `).filter((l)=>l.trim()).slice(-8).join(`
1697
- `);if(/Press enter to confirm or esc to cancel/.test(tail))return{type:"permission",detail:"enter-or-esc gate"};if(/Would you like to run/.test(tail))return{type:"permission",detail:"run-confirmation"};if(/[\u25E6\u25D0\u25D1\u25D2\u25D3\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F]/.test(tail))return{type:"working",detail:"spinner glyph"};if(/esc to interrupt/.test(tail))return{type:"working",detail:"esc-to-interrupt affordance"};if(/^\s*[>\u203A]\s/m.test(tail))return{type:"idle",detail:"prompt detected"};return{type:"working",detail:"between-turns render"}}function mapCodexToExecutorState(state){switch(state){case"working":return"working";case"permission":return"permission";case"idle":return"idle";default:return"idle"}}class CodexProvider{name="codex";transport="api";buildSpawnCommand(ctx){let params=spawnContextToParams3(ctx);return buildCodexCommand(params)}async extractSession(_executor){return null}async detectState(executor){if(executor.state==="terminated"||executor.endedAt)return"terminated";let paneId=executor.tmuxPaneId;if(!paneId)return"working";try{let{capturePaneContent:capturePaneContent2}=await Promise.resolve().then(() => (init_tmux(),exports_tmux)),content=await capturePaneContent2(paneId,50);if(!content||!content.trim())return"working";let result2=detectCodexState(content);return mapCodexToExecutorState(result2.type)}catch{return"working"}}async terminate(executor){if(executor.pid)try{process.kill(executor.pid,"SIGTERM")}catch{}}canResume(){return!1}async deliverMessage(_executorId,_message){}}function spawnContextToParams3(ctx){return{provider:"codex",team:ctx.team,role:ctx.role,skill:ctx.skill,agentId:ctx.agentId,executorId:ctx.executorId,extraArgs:ctx.extraArgs,model:ctx.model,systemPromptFile:ctx.systemPromptFile,systemPrompt:ctx.systemPrompt,promptMode:ctx.promptMode,initialPrompt:ctx.initialPrompt,name:ctx.name,nativeTeam:ctx.nativeTeam,otelPort:ctx.otelPort,otelLogPrompts:ctx.otelLogPrompts,otelWishSlug:ctx.otelWishSlug}}var init_codex=__esm(()=>{init_provider_adapters()});function getProvider(name){return providers.get(name)}var providers,claude,codex,appPty,claudeSdk;var init_registry2=__esm(()=>{init_app_pty();init_claude_code();init_claude_sdk();init_codex();providers=new Map;claude=new ClaudeCodeProvider,codex=new CodexProvider,appPty=new AppPtyProvider,claudeSdk=new ClaudeSdkProvider;providers.set("claude",claude);providers.set("codex",codex);providers.set("app-pty",appPty);providers.set("claude-sdk",claudeSdk)});var exports_wish_state={};__export(exports_wish_state,{wipeState:()=>wipeState,startGroup:()=>startGroup,resolveRepoPath:()=>resolveRepoPath,resetInProgressGroups:()=>resetInProgressGroups,resetGroup:()=>resetGroup,isWishComplete:()=>isWishComplete,getState:()=>getState,getOrCreateState:()=>getOrCreateState,getGroupState:()=>getGroupState,findGroupByAssignee:()=>findGroupByAssignee,findAnyGroupByAssignee:()=>findAnyGroupByAssignee,createState:()=>createState,computeGroupsSignature:()=>computeGroupsSignature,completeGroup:()=>completeGroup,WishStateMismatchError:()=>WishStateMismatchError});import{execSync as execSync9}from"child_process";import{createHash as createHash6}from"crypto";import{existsSync as existsSync41}from"fs";import{dirname as dirname16}from"path";function computeGroupsSignature(groups){let canonical=groups.map((g)=>({name:g.name,dependsOn:[...g.dependsOn??[]].sort()})).sort((a,b2)=>a.name<b2.name?-1:a.name>b2.name?1:0);return createHash6("sha256").update(JSON.stringify(canonical)).digest("hex")}function diffGroups(prev,next){let prevMap=new Map(prev.map((g)=>[g.name,[...g.dependsOn??[]].sort()])),nextMap=new Map(next.map((g)=>[g.name,[...g.dependsOn??[]].sort()])),added=[],removed=[],changed=[];for(let[name,deps]of nextMap)if(!prevMap.has(name))added.push(name);else if(JSON.stringify(prevMap.get(name))!==JSON.stringify(deps))changed.push(name);for(let name of prevMap.keys())if(!nextMap.has(name))removed.push(name);return{added:added.sort(),removed:removed.sort(),changed:changed.sort()}}function normalizeGitPath(path3){if(process.platform!=="darwin")return path3;if(!path3.startsWith("/private/"))return path3;let logicalPath=path3.slice(8);return existsSync41(logicalPath)?logicalPath:path3}function resolveRepoPath(cwd){if(cwd)return cwd;try{let currentDir=process.cwd(),commonDir=execSync9("git rev-parse --path-format=absolute --git-common-dir",{encoding:"utf-8",stdio:["pipe","pipe","pipe"],env:{...process.env,GIT_CEILING_DIRECTORIES:dirname16(currentDir)}}).trim();return normalizeGitPath(dirname16(commonDir))}catch{return normalizeGitPath(process.cwd())}}function wishFilePath(slug){return`.genie/wishes/${slug}/WISH.md`}function toISO(v){if(v==null)return;if(v instanceof Date)return v.toISOString();return String(v)}async function findParent(sql,slug,repoPath){let wishFile=wishFilePath(slug),rows=await sql`
1697
+ `);if(/Press enter to confirm or esc to cancel/.test(tail))return{type:"permission",detail:"enter-or-esc gate"};if(/Would you like to run/.test(tail))return{type:"permission",detail:"run-confirmation"};if(/[\u25E6\u25D0\u25D1\u25D2\u25D3\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F]/.test(tail))return{type:"working",detail:"spinner glyph"};if(/esc to interrupt/.test(tail))return{type:"working",detail:"esc-to-interrupt affordance"};if(/^\s*[>\u203A]\s/m.test(tail))return{type:"idle",detail:"prompt detected"};return{type:"working",detail:"between-turns render"}}function mapCodexToExecutorState(state){switch(state){case"working":return"working";case"permission":return"permission";case"idle":return"idle";default:return"idle"}}class CodexProvider{name="codex";transport="api";buildSpawnCommand(ctx){let params=spawnContextToParams3(ctx);return buildCodexCommand(params)}async extractSession(_executor){return null}async detectState(executor){if(executor.state==="terminated"||executor.endedAt)return"terminated";let paneId=executor.tmuxPaneId;if(!paneId)return"working";try{let{capturePaneContent:capturePaneContent2}=await Promise.resolve().then(() => (init_tmux(),exports_tmux)),content=await capturePaneContent2(paneId,50);if(!content||!content.trim())return"working";let result2=detectCodexState(content);return mapCodexToExecutorState(result2.type)}catch{return"working"}}async terminate(executor){if(executor.pid)try{process.kill(executor.pid,"SIGTERM")}catch{}}canResume(){return!1}async deliverMessage(_executorId,_message){}}function spawnContextToParams3(ctx){return{provider:"codex",team:ctx.team,role:ctx.role,skill:ctx.skill,agentId:ctx.agentId,executorId:ctx.executorId,extraArgs:ctx.extraArgs,model:ctx.model,systemPromptFile:ctx.systemPromptFile,systemPrompt:ctx.systemPrompt,promptMode:ctx.promptMode,initialPrompt:ctx.initialPrompt,name:ctx.name,nativeTeam:ctx.nativeTeam,otelPort:ctx.otelPort,otelLogPrompts:ctx.otelLogPrompts,otelWishSlug:ctx.otelWishSlug}}var init_codex=__esm(()=>{init_provider_adapters()});function getProvider(name){return providers.get(name)}var providers,claude,codex,appPty,claudeSdk;var init_registry2=__esm(()=>{init_app_pty();init_claude_code();init_claude_sdk();init_codex();providers=new Map;claude=new ClaudeCodeProvider,codex=new CodexProvider,appPty=new AppPtyProvider,claudeSdk=new ClaudeSdkProvider;providers.set("claude",claude);providers.set("codex",codex);providers.set("app-pty",appPty);providers.set("claude-sdk",claudeSdk)});var exports_wish_state={};__export(exports_wish_state,{wipeState:()=>wipeState,startGroup:()=>startGroup,resolveRepoPath:()=>resolveRepoPath,resetInProgressGroups:()=>resetInProgressGroups,resetGroup:()=>resetGroup,isWishComplete:()=>isWishComplete,getState:()=>getState,getOrCreateState:()=>getOrCreateState,getGroupState:()=>getGroupState,findGroupByAssignee:()=>findGroupByAssignee,findAnyGroupByAssignee:()=>findAnyGroupByAssignee,createState:()=>createState,computeGroupsSignature:()=>computeGroupsSignature,completeGroup:()=>completeGroup,WishStateMismatchError:()=>WishStateMismatchError});import{execSync as execSync9}from"child_process";import{createHash as createHash6}from"crypto";import{existsSync as existsSync41}from"fs";import{dirname as dirname17}from"path";function computeGroupsSignature(groups){let canonical=groups.map((g)=>({name:g.name,dependsOn:[...g.dependsOn??[]].sort()})).sort((a,b2)=>a.name<b2.name?-1:a.name>b2.name?1:0);return createHash6("sha256").update(JSON.stringify(canonical)).digest("hex")}function diffGroups(prev,next){let prevMap=new Map(prev.map((g)=>[g.name,[...g.dependsOn??[]].sort()])),nextMap=new Map(next.map((g)=>[g.name,[...g.dependsOn??[]].sort()])),added=[],removed=[],changed=[];for(let[name,deps]of nextMap)if(!prevMap.has(name))added.push(name);else if(JSON.stringify(prevMap.get(name))!==JSON.stringify(deps))changed.push(name);for(let name of prevMap.keys())if(!nextMap.has(name))removed.push(name);return{added:added.sort(),removed:removed.sort(),changed:changed.sort()}}function normalizeGitPath(path3){if(process.platform!=="darwin")return path3;if(!path3.startsWith("/private/"))return path3;let logicalPath=path3.slice(8);return existsSync41(logicalPath)?logicalPath:path3}function resolveRepoPath(cwd){if(cwd)return cwd;try{let currentDir=process.cwd(),commonDir=execSync9("git rev-parse --path-format=absolute --git-common-dir",{encoding:"utf-8",stdio:["pipe","pipe","pipe"],env:{...process.env,GIT_CEILING_DIRECTORIES:dirname17(currentDir)}}).trim();return normalizeGitPath(dirname17(commonDir))}catch{return normalizeGitPath(process.cwd())}}function wishFilePath(slug){return`.genie/wishes/${slug}/WISH.md`}function toISO(v){if(v==null)return;if(v instanceof Date)return v.toISOString();return String(v)}async function findParent(sql,slug,repoPath){let wishFile=wishFilePath(slug),rows=await sql`
1698
1698
  SELECT * FROM tasks
1699
1699
  WHERE wish_file = ${wishFile} AND repo_path = ${repoPath} AND parent_id IS NULL
1700
1700
  LIMIT 1
@@ -1847,7 +1847,7 @@ ${gitStatus}`:"","","Pick up where you left off. Read the wish file for full con
1847
1847
  --- Error ---
1848
1848
  ${Array.isArray(error2.errors)&&error2.errors.length>0?error2.errors.join("; "):error2.subtype}\x1B[0m
1849
1849
  `}function formatSystem(msg){let rec=msg;if(rec.subtype==="status"&&rec.status)return`[status] ${rec.status}
1850
- `;return null}var exports_codex_inject={};__export(exports_codex_inject,{injectCodexHooks:()=>injectCodexHooks,codexHooksInjected:()=>codexHooksInjected,CODEX_DISPATCHED_EVENTS:()=>CODEX_DISPATCHED_EVENTS});import{existsSync as existsSync42}from"fs";import{mkdir as mkdir6,readFile as readFile10,writeFile as writeFile7}from"fs/promises";import{homedir as homedir34}from"os";import{join as join50}from"path";function codexHomeDir(){return process.env.CODEX_HOME??join50(homedir34(),".codex")}function codexConfigPath(){return join50(codexHomeDir(),"config.toml")}function escapeTomlString(value){return`"${value.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function buildCodexHookFragment(){let cmd=buildDispatchCommand(),lines=[];lines.push("# === GENIE HOOK BRIDGE BEGIN ==="),lines.push("# Auto-injected by `genie spawn ... --provider codex`. Do not edit by hand."),lines.push("# Removing this block disables codex \u2192 genie hook event delivery."),lines.push("[hooks]"),lines.push("feature_enabled = true"),lines.push("");for(let[event,matcher]of Object.entries(CODEX_DISPATCHED_EVENT_MATCHERS))lines.push(`[[hooks.${event}]]`),lines.push(`matcher = ${escapeTomlString(matcher)}`),lines.push(""),lines.push(`[[hooks.${event}.hooks]]`),lines.push('type = "command"'),lines.push(`command = ${escapeTomlString(cmd)}`),lines.push(`timeout = ${DISPATCH_TIMEOUT2}`),lines.push("");return lines.push("# === GENIE HOOK BRIDGE END ==="),lines.join(`
1850
+ `;return null}var exports_codex_inject={};__export(exports_codex_inject,{injectCodexHooks:()=>injectCodexHooks,codexHooksInjected:()=>codexHooksInjected,CODEX_DISPATCHED_EVENTS:()=>CODEX_DISPATCHED_EVENTS});import{existsSync as existsSync42}from"fs";import{mkdir as mkdir5,readFile as readFile10,writeFile as writeFile7}from"fs/promises";import{homedir as homedir34}from"os";import{join as join50}from"path";function codexHomeDir(){return process.env.CODEX_HOME??join50(homedir34(),".codex")}function codexConfigPath(){return join50(codexHomeDir(),"config.toml")}function escapeTomlString(value){return`"${value.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function buildCodexHookFragment(){let cmd=buildDispatchCommand(),lines=[];lines.push("# === GENIE HOOK BRIDGE BEGIN ==="),lines.push("# Auto-injected by `genie spawn ... --provider codex`. Do not edit by hand."),lines.push("# Removing this block disables codex \u2192 genie hook event delivery."),lines.push("[hooks]"),lines.push("feature_enabled = true"),lines.push("");for(let[event,matcher]of Object.entries(CODEX_DISPATCHED_EVENT_MATCHERS))lines.push(`[[hooks.${event}]]`),lines.push(`matcher = ${escapeTomlString(matcher)}`),lines.push(""),lines.push(`[[hooks.${event}.hooks]]`),lines.push('type = "command"'),lines.push(`command = ${escapeTomlString(cmd)}`),lines.push(`timeout = ${DISPATCH_TIMEOUT2}`),lines.push("");return lines.push("# === GENIE HOOK BRIDGE END ==="),lines.join(`
1851
1851
  `)}function stripExistingBlock(content){let beginIdx=content.indexOf(BEGIN_MARKER),endIdx=content.indexOf(END_MARKER);if(beginIdx===-1||endIdx===-1||endIdx<beginIdx)return{trimmed:content,existed:!1};let before=content.slice(0,beginIdx).replace(/\s+$/,""),after=content.slice(endIdx+END_MARKER.length).replace(/^\s+/,"");return{trimmed:before&&after?`${before}
1852
1852
 
1853
1853
  ${after}
@@ -1856,7 +1856,7 @@ ${after}
1856
1856
 
1857
1857
  ${desired}
1858
1858
  `:`${desired}
1859
- `;if(existing.trim()===candidate.trim())return!1;return await mkdir6(codexHomeDir(),{recursive:!0}),await writeFile7(path3,candidate),!0}async function codexHooksInjected(){let path3=codexConfigPath();if(!existsSync42(path3))return!1;try{let content=await readFile10(path3,"utf-8");return content.includes(BEGIN_MARKER)&&content.includes(END_MARKER)}catch{return!1}}var DISPATCH_TIMEOUT2=15,CODEX_DISPATCHED_EVENTS,BEGIN_MARKER="# === GENIE HOOK BRIDGE BEGIN ===",END_MARKER="# === GENIE HOOK BRIDGE END ===";var init_codex_inject=__esm(()=>{init_inject();init_types2();CODEX_DISPATCHED_EVENTS=Object.keys(CODEX_DISPATCHED_EVENT_MATCHERS)});var exports_idle_timeout={};__export(exports_idle_timeout,{suspendWorker:()=>suspendWorker,getIdleTimeoutMs:()=>getIdleTimeoutMs,checkIdleWorkers:()=>checkIdleWorkers,WATCHDOG_POLL_INTERVAL_MS:()=>WATCHDOG_POLL_INTERVAL_MS});function getIdleTimeoutMs(){let env=process.env.GENIE_IDLE_TIMEOUT_MS;if(env!==void 0){if(env==="")return DEFAULT_IDLE_TIMEOUT_MS;let parsed=Number(env);if(!Number.isNaN(parsed)&&parsed>=0)return parsed}return DEFAULT_IDLE_TIMEOUT_MS}async function suspendWorker(executorId,deps=defaultDeps3){let executor=(await deps.listExecutors()).find((e)=>e.id===executorId);if(!executor)return!1;if(executor.state==="terminated")return!0;if(executor.tmuxPaneId)try{await deps.executeTmux(`kill-pane -t '${executor.tmuxPaneId}'`)}catch{}return await deps.terminateExecutor(executorId),!0}async function checkIdleWorkers(deps=defaultDeps3){let timeoutMs=getIdleTimeoutMs();if(timeoutMs===0)return[];let executors=await deps.listExecutors(),suspended=[];for(let e of executors){if(e.state!=="idle")continue;if(Date.now()-new Date(e.updatedAt).getTime()<timeoutMs)continue;if(e.tmuxPaneId){if(!await deps.isPaneAlive(e.tmuxPaneId)){await deps.terminateExecutor(e.id),suspended.push(e.id);continue}}if(await suspendWorker(e.id,deps))suspended.push(e.id)}return suspended}var defaultDeps3,DEFAULT_IDLE_TIMEOUT_MS=1800000,WATCHDOG_POLL_INTERVAL_MS=60000;var init_idle_timeout=__esm(()=>{init_executor_registry();init_tmux();defaultDeps3={listExecutors:()=>listExecutors(),terminateExecutor,updateExecutorState,executeTmux:executeTmux2,isPaneAlive}});var exports_agents={};__export(exports_agents,{tryAutoRegisterAgent:()=>tryAutoRegisterAgent,resolveTeamName:()=>resolveTeamName3,resolveSpawnIdentity:()=>resolveSpawnIdentity,resolveAgentWorkingDir:()=>resolveAgentWorkingDir,resolveAgentForSpawn:()=>resolveAgentForSpawn,rejectDuplicateRole:()=>rejectDuplicateRole,recoverSurgery:()=>recoverSurgery,pickParallelShortId:()=>pickParallelShortId,killAgentWithDedup:()=>killAgentWithDedup,handleWorkerStop:()=>handleWorkerStop,handleWorkerSpawn:()=>handleWorkerSpawn,handleWorkerResume:()=>handleWorkerResume,handleWorkerRecover:()=>handleWorkerRecover,handleWorkerKill:()=>handleWorkerKill,handleLsCommand:()=>handleLsCommand,findDeadResumable:()=>findDeadResumable,buildWorkerStatusMap:()=>buildWorkerStatusMap,buildResumeContext:()=>buildResumeContext,buildInitialSplitWindowCommand:()=>buildInitialSplitWindowCommand,buildFullResumeParams:()=>buildFullResumeParams,buildDirectoryPermissionSpawnParams:()=>buildDirectoryPermissionSpawnParams,_spawnAutoSyncDeps:()=>_spawnAutoSyncDeps,SpawnPaneVanishedError:()=>SpawnPaneVanishedError,ResumePaneVanishedError:()=>ResumePaneVanishedError,RecoverAgentNotFoundError:()=>RecoverAgentNotFoundError,OwnerSpawnCollisionError:()=>OwnerSpawnCollisionError,AgentReadinessTimeoutError:()=>AgentReadinessTimeoutError});import{existsSync as existsSync43,readFileSync as readFileSync29}from"fs";import{isAbsolute as isAbsolute2,join as join51,relative,resolve as resolvePath}from"path";async function isPaneAliveOrDead(paneId){try{return await isPaneAlive(paneId)}catch(err){let message=err instanceof Error?err.message:String(err);if(err instanceof TmuxUnreachableError||message.includes("no server running")||message.includes("server exited")||message.includes("error connecting"))return!1;throw err}}async function resolveTeamLeaderName(teamNameOrDefault){return await resolveLeaderName(teamNameOrDefault)??teamNameOrDefault}function isRelayAlive(pidFile){let{readFileSync:readFileSync30,existsSync:existsSync44}=__require("fs");if(!existsSync44(pidFile))return!1;try{let pid=Number.parseInt(readFileSync30(pidFile,"utf-8").trim());if(pid>0)return process.kill(pid,0),!0}catch{}return!1}async function ensureOtelRelay(team){let{writeFileSync:writeFileSync17,mkdirSync:mkdirSync19}=__require("fs"),{join:join52}=__require("path"),{homedir:homedir35}=__require("os"),relayDir=join52(homedir35(),".genie","relay");mkdirSync19(relayDir,{recursive:!0});let pidFile=join52(relayDir,"otel-relay.pid"),scriptFile=join52(relayDir,"otel-relay.mjs");if(isRelayAlive(pidFile))return!0;let inboxDir=join52(process.env.CLAUDE_CONFIG_DIR??join52(homedir35(),".claude"),"teams",team,"inboxes"),leaderInboxName=sanitizeTeamName(await resolveTeamLeaderName(team)),escapedRelayDir=relayDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedInboxDir=inboxDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedPidFile=pidFile.replace(/\\/g,"\\\\").replace(/'/g,"\\'");try{writeFileSync17(scriptFile,`import { createServer } from 'http';
1859
+ `;if(existing.trim()===candidate.trim())return!1;return await mkdir5(codexHomeDir(),{recursive:!0}),await writeFile7(path3,candidate),!0}async function codexHooksInjected(){let path3=codexConfigPath();if(!existsSync42(path3))return!1;try{let content=await readFile10(path3,"utf-8");return content.includes(BEGIN_MARKER)&&content.includes(END_MARKER)}catch{return!1}}var DISPATCH_TIMEOUT2=15,CODEX_DISPATCHED_EVENTS,BEGIN_MARKER="# === GENIE HOOK BRIDGE BEGIN ===",END_MARKER="# === GENIE HOOK BRIDGE END ===";var init_codex_inject=__esm(()=>{init_inject();init_types2();CODEX_DISPATCHED_EVENTS=Object.keys(CODEX_DISPATCHED_EVENT_MATCHERS)});var exports_idle_timeout={};__export(exports_idle_timeout,{suspendWorker:()=>suspendWorker,getIdleTimeoutMs:()=>getIdleTimeoutMs,checkIdleWorkers:()=>checkIdleWorkers,WATCHDOG_POLL_INTERVAL_MS:()=>WATCHDOG_POLL_INTERVAL_MS});function getIdleTimeoutMs(){let env=process.env.GENIE_IDLE_TIMEOUT_MS;if(env!==void 0){if(env==="")return DEFAULT_IDLE_TIMEOUT_MS;let parsed=Number(env);if(!Number.isNaN(parsed)&&parsed>=0)return parsed}return DEFAULT_IDLE_TIMEOUT_MS}async function suspendWorker(executorId,deps=defaultDeps3){let executor=(await deps.listExecutors()).find((e)=>e.id===executorId);if(!executor)return!1;if(executor.state==="terminated")return!0;if(executor.tmuxPaneId)try{await deps.executeTmux(`kill-pane -t '${executor.tmuxPaneId}'`)}catch{}return await deps.terminateExecutor(executorId),!0}async function checkIdleWorkers(deps=defaultDeps3){let timeoutMs=getIdleTimeoutMs();if(timeoutMs===0)return[];let executors=await deps.listExecutors(),suspended=[];for(let e of executors){if(e.state!=="idle")continue;if(Date.now()-new Date(e.updatedAt).getTime()<timeoutMs)continue;if(e.tmuxPaneId){if(!await deps.isPaneAlive(e.tmuxPaneId)){await deps.terminateExecutor(e.id),suspended.push(e.id);continue}}if(await suspendWorker(e.id,deps))suspended.push(e.id)}return suspended}var defaultDeps3,DEFAULT_IDLE_TIMEOUT_MS=1800000,WATCHDOG_POLL_INTERVAL_MS=60000;var init_idle_timeout=__esm(()=>{init_executor_registry();init_tmux();defaultDeps3={listExecutors:()=>listExecutors(),terminateExecutor,updateExecutorState,executeTmux:executeTmux2,isPaneAlive}});var exports_agents={};__export(exports_agents,{tryAutoRegisterAgent:()=>tryAutoRegisterAgent,resolveTeamName:()=>resolveTeamName3,resolveSpawnIdentity:()=>resolveSpawnIdentity,resolveAgentWorkingDir:()=>resolveAgentWorkingDir,resolveAgentForSpawn:()=>resolveAgentForSpawn,rejectDuplicateRole:()=>rejectDuplicateRole,recoverSurgery:()=>recoverSurgery,pickParallelShortId:()=>pickParallelShortId,killAgentWithDedup:()=>killAgentWithDedup,handleWorkerStop:()=>handleWorkerStop,handleWorkerSpawn:()=>handleWorkerSpawn,handleWorkerResume:()=>handleWorkerResume,handleWorkerRecover:()=>handleWorkerRecover,handleWorkerKill:()=>handleWorkerKill,handleLsCommand:()=>handleLsCommand,findDeadResumable:()=>findDeadResumable,buildWorkerStatusMap:()=>buildWorkerStatusMap,buildResumeContext:()=>buildResumeContext,buildInitialSplitWindowCommand:()=>buildInitialSplitWindowCommand,buildFullResumeParams:()=>buildFullResumeParams,buildDirectoryPermissionSpawnParams:()=>buildDirectoryPermissionSpawnParams,_spawnAutoSyncDeps:()=>_spawnAutoSyncDeps,SpawnPaneVanishedError:()=>SpawnPaneVanishedError,ResumePaneVanishedError:()=>ResumePaneVanishedError,RecoverAgentNotFoundError:()=>RecoverAgentNotFoundError,OwnerSpawnCollisionError:()=>OwnerSpawnCollisionError,AgentReadinessTimeoutError:()=>AgentReadinessTimeoutError});import{existsSync as existsSync43,readFileSync as readFileSync29}from"fs";import{isAbsolute as isAbsolute2,join as join51,relative,resolve as resolvePath}from"path";async function isPaneAliveOrDead(paneId){try{return await isPaneAlive(paneId)}catch(err){let message=err instanceof Error?err.message:String(err);if(err instanceof TmuxUnreachableError||message.includes("no server running")||message.includes("server exited")||message.includes("error connecting"))return!1;throw err}}async function resolveTeamLeaderName(teamNameOrDefault){return await resolveLeaderName(teamNameOrDefault)??teamNameOrDefault}function isRelayAlive(pidFile){let{readFileSync:readFileSync30,existsSync:existsSync44}=__require("fs");if(!existsSync44(pidFile))return!1;try{let pid=Number.parseInt(readFileSync30(pidFile,"utf-8").trim());if(pid>0)return process.kill(pid,0),!0}catch{}return!1}async function ensureOtelRelay(team){let{writeFileSync:writeFileSync17,mkdirSync:mkdirSync19}=__require("fs"),{join:join52}=__require("path"),{homedir:homedir35}=__require("os"),relayDir=join52(homedir35(),".genie","relay");mkdirSync19(relayDir,{recursive:!0});let pidFile=join52(relayDir,"otel-relay.pid"),scriptFile=join52(relayDir,"otel-relay.mjs");if(isRelayAlive(pidFile))return!0;let inboxDir=join52(process.env.CLAUDE_CONFIG_DIR??join52(homedir35(),".claude"),"teams",team,"inboxes"),leaderInboxName=sanitizeTeamName(await resolveTeamLeaderName(team)),escapedRelayDir=relayDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedInboxDir=inboxDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedPidFile=pidFile.replace(/\\/g,"\\\\").replace(/'/g,"\\'");try{writeFileSync17(scriptFile,`import { createServer } from 'http';
1860
1860
  import { execSync } from 'child_process';
1861
1861
  import { readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'fs';
1862
1862
  import { createHash } from 'crypto';
@@ -2238,7 +2238,7 @@ ${bodyHash}`}function signOmniRequest(method,path3,body){let paths=keyPaths(),ho
2238
2238
  [omni-signature] Run \`genie omni handshake\` to register this host and enable signed requests.
2239
2239
  `)}return null}let timestamp2=new Date().toISOString(),canonical=canonicalSigningInput(timestamp2,method,path3,body),signature=sign(null,Buffer.from(canonical,"utf-8"),key).toString("base64url");return{"X-Genie-Host-Id":host.hostId,"X-Genie-Timestamp":timestamp2,"X-Genie-Signature":signature}}var warnedMissingKey=!1,cachedKey=null,cachedKeyPath=null;var init_omni_signature=()=>{};var exports_frontmatter_writer={};__export(exports_frontmatter_writer,{writeFrontmatter:()=>writeFrontmatter,serializeSdkConfig:()=>serializeSdkConfig});import{readFileSync as readFileSync31,writeFileSync as writeFileSync17}from"fs";function writeFrontmatter(filePath,updates){let content=readFileSync31(filePath,"utf-8"),{yamlObj,body}=splitFrontmatter(content),merged={...yamlObj,...stripUndefined(updates)},output=`---
2240
2240
  ${dump(merged,{lineWidth:-1,noRefs:!0,sortKeys:!1,quotingType:'"'})}---
2241
- ${body}`;writeFileSync17(filePath,output,"utf-8")}function serializeSdkConfig(sdk){let result2={};for(let[key,value]of Object.entries(sdk)){if(value===void 0||value===null)continue;if(Array.isArray(value)&&value.length===0)continue;if(typeof value==="object"&&!Array.isArray(value)&&Object.keys(value).length===0)continue;result2[key]=value}return result2}function splitFrontmatter(content){let match=content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!match)return{yamlObj:{},body:content};let yamlStr=match[1],body=match[2],yamlObj={};try{let parsed=load(yamlStr);if(typeof parsed==="object"&&parsed!==null)yamlObj=parsed}catch{}return{yamlObj,body}}function stripUndefined(obj){let result2={};for(let[key,value]of Object.entries(obj))if(value!==void 0)result2[key]=value;return result2}var init_frontmatter_writer=__esm(()=>{init_js_yaml()});import{existsSync as existsSync46,realpathSync as realpathSync6}from"fs";import{homedir as homedir36}from"os";import{join as join55,resolve as resolve8}from"path";function getCwd(deps){return deps.cwd??process.cwd()}function getHomeDir(deps){return deps.homeDir??homedir36()}function getWorkspaceRoot(deps){if("workspaceRoot"in deps)return deps.workspaceRoot??null;return findWorkspace()?.root??null}function getConfig(deps){return deps.config??loadGenieConfigSync()}function expandHome(path3,homeDir){if(path3==="~")return homeDir;if(path3.startsWith("~/"))return join55(homeDir,path3.slice(2));return path3}function normalizeBrainVaultPath(path3,deps){return resolve8(getCwd(deps),expandHome(path3,getHomeDir(deps)))}function canonicalBrainVaultPath(path3,deps){let realpath=deps.realpath??realpathSync6;try{return realpath(path3)}catch{return resolve8(path3)}}function dedupeBrainVaultPaths(paths,deps={}){let seen=new Set,deduped=[];for(let path3 of paths){let canonical=canonicalBrainVaultPath(path3,deps);if(seen.has(canonical))continue;seen.add(canonical),deduped.push(canonical)}return deduped}function hasBrainJson(path3,deps){return(deps.exists??existsSync46)(join55(path3,"brain.json"))}function filterVaultsWithBrainJson(paths,source,deps){let warn=deps.warn??console.warn,label=source==="config"?"configured":source==="registry"?"registered":"legacy",valid=[];for(let path3 of paths){if(hasBrainJson(path3,deps)){valid.push(path3);continue}warn(` Brain server: skipped ${label} vault ${path3} (missing brain.json)`)}return valid}function normalizeAndDedupe(paths,deps){return dedupeBrainVaultPaths(paths.map((path3)=>normalizeBrainVaultPath(path3,deps)),deps)}function pushPathFromEntry(entry2,paths){let found=!1;for(let field of REGISTRY_PATH_FIELDS){let value=entry2[field];if(typeof value==="string"&&value.trim().length>0)paths.push(value),found=!0}return found}function isRegistryRecord(value){return Boolean(value)&&typeof value==="object"&&!Array.isArray(value)}function collectRegistryArray(values2,paths){for(let item of values2)collectRegistryPaths(item,paths)}function collectRegistryObject(entry2,paths){let foundPath=pushPathFromEntry(entry2,paths);for(let field of REGISTRY_COLLECTION_FIELDS)if(field in entry2)collectRegistryPaths(entry2[field],paths);if(!foundPath){for(let item of Object.values(entry2))if(item&&typeof item==="object")collectRegistryPaths(item,paths)}}function collectRegistryPaths(value,paths){if(typeof value==="string"){if(value.trim().length>0)paths.push(value);return}if(Array.isArray(value)){collectRegistryArray(value,paths);return}if(isRegistryRecord(value))collectRegistryObject(value,paths)}function countRegistryItems(value,fallback){if(Array.isArray(value))return value.length;if(!isRegistryRecord(value))return fallback;for(let field of REGISTRY_COLLECTION_FIELDS){let collection=value[field];if(Array.isArray(collection))return collection.length;if(isRegistryRecord(collection))return Object.keys(collection).length}return fallback}async function discoverRegisteredBrainVaultPaths(deps){let brain=deps.brain;if(!brain)return{paths:[],registryCount:0};let registryCalls=["listBrains","listBrainVaults","listVaults","listRegisteredBrains","listRegisteredBrainVaults","getBrainRegistry","readBrainRegistry"];for(let name of registryCalls){let read=brain[name];if(typeof read!=="function")continue;try{let result2=await read.call(brain),paths=[];if(collectRegistryPaths(result2,paths),paths.length>0)return{paths,registryCount:countRegistryItems(result2,paths.length)}}catch(err){let msg=err instanceof Error?err.message:String(err);(deps.warn??console.warn)(` Brain registry: ${name} failed: ${msg}`)}}return{paths:[],registryCount:0}}async function findLegacyBrainVault(deps={}){let cwd=getCwd(deps),homeDir=getHomeDir(deps),workspaceRoot=getWorkspaceRoot(deps),candidates=[workspaceRoot?join55(workspaceRoot,"brain"):void 0,cwd,join55(cwd,"brain"),join55(homeDir,"brain")].filter((path3)=>typeof path3==="string");for(let path3 of normalizeAndDedupe(candidates,deps))if(hasBrainJson(path3,deps))return path3;return null}async function findBrainVault(deps={}){return(await resolveBrainVaults(deps)).paths[0]??null}async function resolveBrainVaults(deps={}){let configuredPaths=getConfig(deps).brain?.paths;if(Array.isArray(configuredPaths)&&configuredPaths.length>0)return{source:"config",paths:filterVaultsWithBrainJson(normalizeAndDedupe(configuredPaths,deps),"config",deps)};let registered=await discoverRegisteredBrainVaultPaths(deps);if(registered.paths.length>0)return{source:"registry",paths:filterVaultsWithBrainJson(normalizeAndDedupe(registered.paths,deps),"registry",deps),registryCount:registered.registryCount};let legacyPath=await findLegacyBrainVault(deps);return{source:"legacy",paths:legacyPath?[legacyPath]:[]}}function normalizeStartupConcurrency(value){if(typeof value!=="number"||!Number.isFinite(value))return DEFAULT_BRAIN_START_CONCURRENCY;return Math.max(1,Math.floor(value))}async function allSettledBounded(items,concurrency,worker){let results=Array(items.length),nextIndex=0;async function runWorker(){while(!0){let index=nextIndex++;if(index>=items.length)return;try{results[index]={status:"fulfilled",value:await worker(items[index],index)}}catch(reason){results[index]={status:"rejected",reason}}}}return await Promise.allSettled(Array.from({length:Math.min(concurrency,items.length)},()=>runWorker())),results}function warnRegistryDrift(resolution,startedCount,resolvedCount,deps){if(resolution.source!=="registry")return;let expectedCount=resolution.registryCount??resolvedCount;if(startedCount===expectedCount)return;(deps.warn??console.warn)(` Brain server: registry drift: started ${startedCount}/${expectedCount} registered vault(s) (${resolvedCount} resolved valid path(s))`)}async function startResolvedBrainVaults(resolution,brain,geniePgPort,deps={}){let startEmbeddedBrainServer=brain.startEmbeddedBrainServer;if(!startEmbeddedBrainServer)return[];let warn=deps.warn??console.warn,log2=deps.log??console.log,handles=[],paths=dedupeBrainVaultPaths(resolution.paths,deps),concurrency=normalizeStartupConcurrency(deps.startupConcurrency),results=await allSettledBounded(paths,concurrency,async(brainPath)=>{let handle=await startEmbeddedBrainServer.call(brain,{brainPath,geniePgPort});return log2(` Brain server ready on port ${handle.port} (${brainPath})`),{brainPath,port:handle.port,stop:handle.stop}});for(let index=0;index<results.length;index++){let result2=results[index];if(result2.status==="fulfilled")handles.push(result2.value);else{let msg=result2.reason instanceof Error?result2.reason.message:String(result2.reason);warn(` Brain server: failed for ${paths[index]}: ${msg}`)}}return warnRegistryDrift(resolution,handles.length,paths.length,deps),handles}var REGISTRY_PATH_FIELDS,REGISTRY_COLLECTION_FIELDS,DEFAULT_BRAIN_START_CONCURRENCY=4;var init_brain_vaults=__esm(()=>{init_genie_config2();init_workspace();REGISTRY_PATH_FIELDS=["homePath","brainPath","vaultPath","path","root","dir"],REGISTRY_COLLECTION_FIELDS=["paths","brains","vaults","entries","items","registered"]});var exports_tui_disable={};__export(exports_tui_disable,{noticeTuiSkipped:()=>noticeTuiSkipped,isTuiDisabled:()=>isTuiDisabled});function isTuiDisabled(){let envVal=process.env.GENIE_TUI_DISABLE;if(envVal&&TRUTHY2.has(envVal.trim().toLowerCase()))return!0;if(process.argv.includes("--no-tui"))return!0;if(!process.stdout.isTTY)return!0;return!1}function noticeTuiSkipped(context){let envVal=process.env.GENIE_TUI_DISABLE,reason=envVal&&TRUTHY2.has(envVal.trim().toLowerCase())?"GENIE_TUI_DISABLE is set":process.argv.includes("--no-tui")?"--no-tui flag present":"stdout is not a TTY";console.error(`genie: TUI ${context} skipped (${reason}). See https://github.com/automagik-dev/genie for status of the upstream OpenTUI kqueue spin on macOS.`)}var TRUTHY2;var init_tui_disable=__esm(()=>{TRUTHY2=new Set(["1","true","yes","on"])});var exports_service_registry={};__export(exports_service_registry,{unregisterService:()=>unregisterService,registerService:()=>registerService,reapDeadServices:()=>reapDeadServices,killAllServices:()=>killAllServices,getRegisteredServices:()=>getRegisteredServices,clearRegistry:()=>clearRegistry});function registerService(name,pid){registry.set(name,{pid,name,startedAt:new Date})}function unregisterService(name){registry.delete(name)}function getRegisteredServices(){return Array.from(registry.values())}function reapDeadServices(){let reaped=[];for(let[name,entry2]of registry)try{process.kill(entry2.pid,0)}catch{registry.delete(name),reaped.push(name)}return reaped}function killAllServices(){for(let[_name,entry2]of registry)try{process.kill(entry2.pid,"SIGTERM")}catch{registry.delete(_name)}let deadline=Date.now()+3000,checkInterval=200,stillAlive=()=>{for(let[,entry2]of registry)try{return process.kill(entry2.pid,0),!0}catch{}return!1};while(Date.now()<deadline&&stillAlive()){let waitUntil=Date.now()+checkInterval;while(Date.now()<waitUntil);}for(let[name,entry2]of registry){try{process.kill(entry2.pid,0),process.kill(entry2.pid,"SIGKILL")}catch{}registry.delete(name)}}function clearRegistry(){registry.clear()}var registry;var init_service_registry=__esm(()=>{registry=new Map});function parseDuration(input){let match=input.trim().match(DURATION_RE);if(!match)throw Error(`Invalid duration: "${input}". Expected format: 10m, 2h, 24h, 1d`);let value=Number.parseFloat(match[1]),unit=match[2].toLowerCase(),ms=value*{s:1000,sec:1000,m:60000,min:60000,h:3600000,hr:3600000,d:86400000,day:86400000}[unit];if(ms<=0)throw Error(`Duration must be positive: "${input}"`);return ms}function expandRange(range,step,min,max){if(step===0)throw Error("Cron step value cannot be 0");if(range==="*"){let out=[];for(let i2=min;i2<=max;i2+=step)out.push(i2);return out}if(range.includes("-")){let[start,end]=range.split("-").map(Number),out=[];for(let i2=start;i2<=end;i2+=step)out.push(i2);return out}return[Number.parseInt(range,10)]}function parseCronField(field,min,max){let values2=new Set;for(let part of field.split(",")){let stepMatch=part.match(/^(.+)\/(\d+)$/),step=stepMatch?Number.parseInt(stepMatch[2],10):1,range=stepMatch?stepMatch[1]:part;for(let v of expandRange(range,step,min,max))values2.add(v)}return[...values2].sort((a,b2)=>a-b2)}function getTimeParts(date,tz){if(!tz)return{month:date.getMonth()+1,dom:date.getDate(),dow:date.getDay(),hour:date.getHours(),minute:date.getMinutes()};let parts=new Intl.DateTimeFormat("en-US",{timeZone:tz,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",weekday:"short",hour12:!1}).formatToParts(date),get3=(type2)=>Number(parts.find((p)=>p.type===type2)?.value??0),dayMap={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6},weekday=parts.find((p)=>p.type==="weekday")?.value??"Sun";return{month:get3("month"),dom:get3("day"),dow:dayMap[weekday]??0,hour:get3("hour")===24?0:get3("hour"),minute:get3("minute")}}function parseOpts(afterOrOpts){if(afterOrOpts instanceof Date)return{after:afterOrOpts};if(afterOrOpts)return{after:afterOrOpts.after,timezone:afterOrOpts.timezone};return{}}function advanceToNextDay(candidate,tz){candidate.setTime(candidate.getTime()+86400000);let tp=getTimeParts(candidate,tz);candidate.setTime(candidate.getTime()-tp.hour*3600000-tp.minute*60000)}function parseCronExpr(cronExpr){let parts=cronExpr.trim().split(/\s+/);if(parts.length<5)throw Error(`Invalid cron expression: "${cronExpr}"`);let[minField,hourField,domField,monthField,dowField]=parts;return{minutes:parseCronField(minField,0,59),hours:parseCronField(hourField,0,23),doms:parseCronField(domField,1,31),months:parseCronField(monthField,1,12),dows:parseCronField(dowField,0,6),domRestricted:domField!=="*",dowRestricted:dowField!=="*"}}function computeNextCronDue(cronExpr,afterOrOpts){let{after,timezone}=parseOpts(afterOrOpts),cron=parseCronExpr(cronExpr),candidate=new Date((after??new Date).getTime());candidate.setSeconds(0,0),candidate.setTime(candidate.getTime()+60000);let limit=new Date(candidate.getTime()+31622400000);while(candidate<=limit){let tp=getTimeParts(candidate,timezone);if(!cron.months.includes(tp.month)){advanceToNextDay(candidate,timezone);continue}if(!(cron.domRestricted&&cron.dowRestricted?cron.doms.includes(tp.dom)||cron.dows.includes(tp.dow):cron.doms.includes(tp.dom)&&cron.dows.includes(tp.dow))){advanceToNextDay(candidate,timezone);continue}if(!cron.hours.includes(tp.hour)){candidate.setTime(candidate.getTime()+3600000-tp.minute*60000);continue}if(cron.minutes.includes(tp.minute))return candidate;candidate.setTime(candidate.getTime()+60000)}throw Error(`No next cron occurrence found for "${cronExpr}" within 366 days`)}var DURATION_RE;var init_cron=__esm(()=>{DURATION_RE=/^(\d+(?:\.\d+)?)\s*(s|sec|m|min|h|hr|d|day)s?$/i});import{randomUUID as randomUUID7}from"crypto";function parseNotifyPayload(channel,raw){switch(channel){case"genie_task_stage":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:"task.stage_change",payload:{taskId:parts[0],fromStage:parts[1],toStage:parts[2]},taskId:parts[0],summary:`Task ${parts[0]} moved from ${parts[1]} to ${parts[2]}`}}case"genie_executor_state":{let parts=raw.split(":");if(parts.length<4)return null;let eventType=parts[3]==="error"?"executor.error":"executor.state_change";return{channel,eventType,payload:{executorId:parts[0],agentId:parts[1],oldState:parts[2],newState:parts[3]},agentId:parts[1],summary:`${parts[1]} state: ${parts[2]} \u2192 ${parts[3]}`}}case"genie_message":{let parts=raw.split(":");if(parts.length<2)return null;return{channel,eventType:"task.comment",payload:{messageId:parts[0],conversationId:parts[1]},summary:`New message in conversation ${parts[1]}`}}case"genie_audit_event":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:`${parts[0]}.${parts[2]}`,payload:{entityType:parts[0],entityId:parts[1],auditEventType:parts[2]},summary:`${parts[0]} ${parts[1]}: ${parts[2]}`}}default:return null}}function isActionableEvent(eventType){return ACTIONABLE_EVENTS.has(eventType)||eventType.startsWith("request.")}async function resolveTargetTeams(event){if(!isActionableEvent(event.eventType))return[];let active=(await listTeams()).filter((t)=>t.status==="in_progress");if(event.agentId){let aid=event.agentId;return active.filter((t)=>t.members.includes(aid)||t.leader===aid).map((t)=>t.name)}return active.map((t)=>t.name)}async function writeMailbox(repoPath,leader,message,traceId){try{await(await getConnection())`
2241
+ ${body}`;writeFileSync17(filePath,output,"utf-8")}function serializeSdkConfig(sdk){let result2={};for(let[key,value]of Object.entries(sdk)){if(value===void 0||value===null)continue;if(Array.isArray(value)&&value.length===0)continue;if(typeof value==="object"&&!Array.isArray(value)&&Object.keys(value).length===0)continue;result2[key]=value}return result2}function splitFrontmatter(content){let match=content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!match)return{yamlObj:{},body:content};let yamlStr=match[1],body=match[2],yamlObj={};try{let parsed=load(yamlStr);if(typeof parsed==="object"&&parsed!==null)yamlObj=parsed}catch{}return{yamlObj,body}}function stripUndefined(obj){let result2={};for(let[key,value]of Object.entries(obj))if(value!==void 0)result2[key]=value;return result2}var init_frontmatter_writer=__esm(()=>{init_js_yaml()});import{existsSync as existsSync46,realpathSync as realpathSync7}from"fs";import{homedir as homedir36}from"os";import{join as join55,resolve as resolve8}from"path";function getCwd(deps){return deps.cwd??process.cwd()}function getHomeDir(deps){return deps.homeDir??homedir36()}function getWorkspaceRoot(deps){if("workspaceRoot"in deps)return deps.workspaceRoot??null;return findWorkspace()?.root??null}function getConfig(deps){return deps.config??loadGenieConfigSync()}function expandHome(path3,homeDir){if(path3==="~")return homeDir;if(path3.startsWith("~/"))return join55(homeDir,path3.slice(2));return path3}function normalizeBrainVaultPath(path3,deps){return resolve8(getCwd(deps),expandHome(path3,getHomeDir(deps)))}function canonicalBrainVaultPath(path3,deps){let realpath=deps.realpath??realpathSync7;try{return realpath(path3)}catch{return resolve8(path3)}}function dedupeBrainVaultPaths(paths,deps={}){let seen=new Set,deduped=[];for(let path3 of paths){let canonical=canonicalBrainVaultPath(path3,deps);if(seen.has(canonical))continue;seen.add(canonical),deduped.push(canonical)}return deduped}function hasBrainJson(path3,deps){return(deps.exists??existsSync46)(join55(path3,"brain.json"))}function filterVaultsWithBrainJson(paths,source,deps){let warn=deps.warn??console.warn,label=source==="config"?"configured":source==="registry"?"registered":"legacy",valid=[];for(let path3 of paths){if(hasBrainJson(path3,deps)){valid.push(path3);continue}warn(` Brain server: skipped ${label} vault ${path3} (missing brain.json)`)}return valid}function normalizeAndDedupe(paths,deps){return dedupeBrainVaultPaths(paths.map((path3)=>normalizeBrainVaultPath(path3,deps)),deps)}function pushPathFromEntry(entry2,paths){let found=!1;for(let field of REGISTRY_PATH_FIELDS){let value=entry2[field];if(typeof value==="string"&&value.trim().length>0)paths.push(value),found=!0}return found}function isRegistryRecord(value){return Boolean(value)&&typeof value==="object"&&!Array.isArray(value)}function collectRegistryArray(values2,paths){for(let item of values2)collectRegistryPaths(item,paths)}function collectRegistryObject(entry2,paths){let foundPath=pushPathFromEntry(entry2,paths);for(let field of REGISTRY_COLLECTION_FIELDS)if(field in entry2)collectRegistryPaths(entry2[field],paths);if(!foundPath){for(let item of Object.values(entry2))if(item&&typeof item==="object")collectRegistryPaths(item,paths)}}function collectRegistryPaths(value,paths){if(typeof value==="string"){if(value.trim().length>0)paths.push(value);return}if(Array.isArray(value)){collectRegistryArray(value,paths);return}if(isRegistryRecord(value))collectRegistryObject(value,paths)}function countRegistryItems(value,fallback){if(Array.isArray(value))return value.length;if(!isRegistryRecord(value))return fallback;for(let field of REGISTRY_COLLECTION_FIELDS){let collection=value[field];if(Array.isArray(collection))return collection.length;if(isRegistryRecord(collection))return Object.keys(collection).length}return fallback}async function discoverRegisteredBrainVaultPaths(deps){let brain=deps.brain;if(!brain)return{paths:[],registryCount:0};let registryCalls=["listBrains","listBrainVaults","listVaults","listRegisteredBrains","listRegisteredBrainVaults","getBrainRegistry","readBrainRegistry"];for(let name of registryCalls){let read=brain[name];if(typeof read!=="function")continue;try{let result2=await read.call(brain),paths=[];if(collectRegistryPaths(result2,paths),paths.length>0)return{paths,registryCount:countRegistryItems(result2,paths.length)}}catch(err){let msg=err instanceof Error?err.message:String(err);(deps.warn??console.warn)(` Brain registry: ${name} failed: ${msg}`)}}return{paths:[],registryCount:0}}async function findLegacyBrainVault(deps={}){let cwd=getCwd(deps),homeDir=getHomeDir(deps),workspaceRoot=getWorkspaceRoot(deps),candidates=[workspaceRoot?join55(workspaceRoot,"brain"):void 0,cwd,join55(cwd,"brain"),join55(homeDir,"brain")].filter((path3)=>typeof path3==="string");for(let path3 of normalizeAndDedupe(candidates,deps))if(hasBrainJson(path3,deps))return path3;return null}async function findBrainVault(deps={}){return(await resolveBrainVaults(deps)).paths[0]??null}async function resolveBrainVaults(deps={}){let configuredPaths=getConfig(deps).brain?.paths;if(Array.isArray(configuredPaths)&&configuredPaths.length>0)return{source:"config",paths:filterVaultsWithBrainJson(normalizeAndDedupe(configuredPaths,deps),"config",deps)};let registered=await discoverRegisteredBrainVaultPaths(deps);if(registered.paths.length>0)return{source:"registry",paths:filterVaultsWithBrainJson(normalizeAndDedupe(registered.paths,deps),"registry",deps),registryCount:registered.registryCount};let legacyPath=await findLegacyBrainVault(deps);return{source:"legacy",paths:legacyPath?[legacyPath]:[]}}function normalizeStartupConcurrency(value){if(typeof value!=="number"||!Number.isFinite(value))return DEFAULT_BRAIN_START_CONCURRENCY;return Math.max(1,Math.floor(value))}async function allSettledBounded(items,concurrency,worker){let results=Array(items.length),nextIndex=0;async function runWorker(){while(!0){let index=nextIndex++;if(index>=items.length)return;try{results[index]={status:"fulfilled",value:await worker(items[index],index)}}catch(reason){results[index]={status:"rejected",reason}}}}return await Promise.allSettled(Array.from({length:Math.min(concurrency,items.length)},()=>runWorker())),results}function warnRegistryDrift(resolution,startedCount,resolvedCount,deps){if(resolution.source!=="registry")return;let expectedCount=resolution.registryCount??resolvedCount;if(startedCount===expectedCount)return;(deps.warn??console.warn)(` Brain server: registry drift: started ${startedCount}/${expectedCount} registered vault(s) (${resolvedCount} resolved valid path(s))`)}async function startResolvedBrainVaults(resolution,brain,geniePgPort,deps={}){let startEmbeddedBrainServer=brain.startEmbeddedBrainServer;if(!startEmbeddedBrainServer)return[];let warn=deps.warn??console.warn,log2=deps.log??console.log,handles=[],paths=dedupeBrainVaultPaths(resolution.paths,deps),concurrency=normalizeStartupConcurrency(deps.startupConcurrency),results=await allSettledBounded(paths,concurrency,async(brainPath)=>{let handle=await startEmbeddedBrainServer.call(brain,{brainPath,geniePgPort});return log2(` Brain server ready on port ${handle.port} (${brainPath})`),{brainPath,port:handle.port,stop:handle.stop}});for(let index=0;index<results.length;index++){let result2=results[index];if(result2.status==="fulfilled")handles.push(result2.value);else{let msg=result2.reason instanceof Error?result2.reason.message:String(result2.reason);warn(` Brain server: failed for ${paths[index]}: ${msg}`)}}return warnRegistryDrift(resolution,handles.length,paths.length,deps),handles}var REGISTRY_PATH_FIELDS,REGISTRY_COLLECTION_FIELDS,DEFAULT_BRAIN_START_CONCURRENCY=4;var init_brain_vaults=__esm(()=>{init_genie_config2();init_workspace();REGISTRY_PATH_FIELDS=["homePath","brainPath","vaultPath","path","root","dir"],REGISTRY_COLLECTION_FIELDS=["paths","brains","vaults","entries","items","registered"]});var exports_tui_disable={};__export(exports_tui_disable,{noticeTuiSkipped:()=>noticeTuiSkipped,isTuiDisabled:()=>isTuiDisabled});function isTuiDisabled(){let envVal=process.env.GENIE_TUI_DISABLE;if(envVal&&TRUTHY2.has(envVal.trim().toLowerCase()))return!0;if(process.argv.includes("--no-tui"))return!0;if(!process.stdout.isTTY)return!0;return!1}function noticeTuiSkipped(context){let envVal=process.env.GENIE_TUI_DISABLE,reason=envVal&&TRUTHY2.has(envVal.trim().toLowerCase())?"GENIE_TUI_DISABLE is set":process.argv.includes("--no-tui")?"--no-tui flag present":"stdout is not a TTY";console.error(`genie: TUI ${context} skipped (${reason}). See https://github.com/automagik-dev/genie for status of the upstream OpenTUI kqueue spin on macOS.`)}var TRUTHY2;var init_tui_disable=__esm(()=>{TRUTHY2=new Set(["1","true","yes","on"])});var exports_service_registry={};__export(exports_service_registry,{unregisterService:()=>unregisterService,registerService:()=>registerService,reapDeadServices:()=>reapDeadServices,killAllServices:()=>killAllServices,getRegisteredServices:()=>getRegisteredServices,clearRegistry:()=>clearRegistry});function registerService(name,pid){registry.set(name,{pid,name,startedAt:new Date})}function unregisterService(name){registry.delete(name)}function getRegisteredServices(){return Array.from(registry.values())}function reapDeadServices(){let reaped=[];for(let[name,entry2]of registry)try{process.kill(entry2.pid,0)}catch{registry.delete(name),reaped.push(name)}return reaped}function killAllServices(){for(let[_name,entry2]of registry)try{process.kill(entry2.pid,"SIGTERM")}catch{registry.delete(_name)}let deadline=Date.now()+3000,checkInterval=200,stillAlive=()=>{for(let[,entry2]of registry)try{return process.kill(entry2.pid,0),!0}catch{}return!1};while(Date.now()<deadline&&stillAlive()){let waitUntil=Date.now()+checkInterval;while(Date.now()<waitUntil);}for(let[name,entry2]of registry){try{process.kill(entry2.pid,0),process.kill(entry2.pid,"SIGKILL")}catch{}registry.delete(name)}}function clearRegistry(){registry.clear()}var registry;var init_service_registry=__esm(()=>{registry=new Map});function parseDuration(input){let match=input.trim().match(DURATION_RE);if(!match)throw Error(`Invalid duration: "${input}". Expected format: 10m, 2h, 24h, 1d`);let value=Number.parseFloat(match[1]),unit=match[2].toLowerCase(),ms=value*{s:1000,sec:1000,m:60000,min:60000,h:3600000,hr:3600000,d:86400000,day:86400000}[unit];if(ms<=0)throw Error(`Duration must be positive: "${input}"`);return ms}function expandRange(range,step,min,max){if(step===0)throw Error("Cron step value cannot be 0");if(range==="*"){let out=[];for(let i2=min;i2<=max;i2+=step)out.push(i2);return out}if(range.includes("-")){let[start,end]=range.split("-").map(Number),out=[];for(let i2=start;i2<=end;i2+=step)out.push(i2);return out}return[Number.parseInt(range,10)]}function parseCronField(field,min,max){let values2=new Set;for(let part of field.split(",")){let stepMatch=part.match(/^(.+)\/(\d+)$/),step=stepMatch?Number.parseInt(stepMatch[2],10):1,range=stepMatch?stepMatch[1]:part;for(let v of expandRange(range,step,min,max))values2.add(v)}return[...values2].sort((a,b2)=>a-b2)}function getTimeParts(date,tz){if(!tz)return{month:date.getMonth()+1,dom:date.getDate(),dow:date.getDay(),hour:date.getHours(),minute:date.getMinutes()};let parts=new Intl.DateTimeFormat("en-US",{timeZone:tz,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",weekday:"short",hour12:!1}).formatToParts(date),get3=(type2)=>Number(parts.find((p)=>p.type===type2)?.value??0),dayMap={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6},weekday=parts.find((p)=>p.type==="weekday")?.value??"Sun";return{month:get3("month"),dom:get3("day"),dow:dayMap[weekday]??0,hour:get3("hour")===24?0:get3("hour"),minute:get3("minute")}}function parseOpts(afterOrOpts){if(afterOrOpts instanceof Date)return{after:afterOrOpts};if(afterOrOpts)return{after:afterOrOpts.after,timezone:afterOrOpts.timezone};return{}}function advanceToNextDay(candidate,tz){candidate.setTime(candidate.getTime()+86400000);let tp=getTimeParts(candidate,tz);candidate.setTime(candidate.getTime()-tp.hour*3600000-tp.minute*60000)}function parseCronExpr(cronExpr){let parts=cronExpr.trim().split(/\s+/);if(parts.length<5)throw Error(`Invalid cron expression: "${cronExpr}"`);let[minField,hourField,domField,monthField,dowField]=parts;return{minutes:parseCronField(minField,0,59),hours:parseCronField(hourField,0,23),doms:parseCronField(domField,1,31),months:parseCronField(monthField,1,12),dows:parseCronField(dowField,0,6),domRestricted:domField!=="*",dowRestricted:dowField!=="*"}}function computeNextCronDue(cronExpr,afterOrOpts){let{after,timezone}=parseOpts(afterOrOpts),cron=parseCronExpr(cronExpr),candidate=new Date((after??new Date).getTime());candidate.setSeconds(0,0),candidate.setTime(candidate.getTime()+60000);let limit=new Date(candidate.getTime()+31622400000);while(candidate<=limit){let tp=getTimeParts(candidate,timezone);if(!cron.months.includes(tp.month)){advanceToNextDay(candidate,timezone);continue}if(!(cron.domRestricted&&cron.dowRestricted?cron.doms.includes(tp.dom)||cron.dows.includes(tp.dow):cron.doms.includes(tp.dom)&&cron.dows.includes(tp.dow))){advanceToNextDay(candidate,timezone);continue}if(!cron.hours.includes(tp.hour)){candidate.setTime(candidate.getTime()+3600000-tp.minute*60000);continue}if(cron.minutes.includes(tp.minute))return candidate;candidate.setTime(candidate.getTime()+60000)}throw Error(`No next cron occurrence found for "${cronExpr}" within 366 days`)}var DURATION_RE;var init_cron=__esm(()=>{DURATION_RE=/^(\d+(?:\.\d+)?)\s*(s|sec|m|min|h|hr|d|day)s?$/i});import{randomUUID as randomUUID7}from"crypto";function parseNotifyPayload(channel,raw){switch(channel){case"genie_task_stage":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:"task.stage_change",payload:{taskId:parts[0],fromStage:parts[1],toStage:parts[2]},taskId:parts[0],summary:`Task ${parts[0]} moved from ${parts[1]} to ${parts[2]}`}}case"genie_executor_state":{let parts=raw.split(":");if(parts.length<4)return null;let eventType=parts[3]==="error"?"executor.error":"executor.state_change";return{channel,eventType,payload:{executorId:parts[0],agentId:parts[1],oldState:parts[2],newState:parts[3]},agentId:parts[1],summary:`${parts[1]} state: ${parts[2]} \u2192 ${parts[3]}`}}case"genie_message":{let parts=raw.split(":");if(parts.length<2)return null;return{channel,eventType:"task.comment",payload:{messageId:parts[0],conversationId:parts[1]},summary:`New message in conversation ${parts[1]}`}}case"genie_audit_event":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:`${parts[0]}.${parts[2]}`,payload:{entityType:parts[0],entityId:parts[1],auditEventType:parts[2]},summary:`${parts[0]} ${parts[1]}: ${parts[2]}`}}default:return null}}function isActionableEvent(eventType){return ACTIONABLE_EVENTS.has(eventType)||eventType.startsWith("request.")}async function resolveTargetTeams(event){if(!isActionableEvent(event.eventType))return[];let active=(await listTeams()).filter((t)=>t.status==="in_progress");if(event.agentId){let aid=event.agentId;return active.filter((t)=>t.members.includes(aid)||t.leader===aid).map((t)=>t.name)}return active.map((t)=>t.name)}async function writeMailbox(repoPath,leader,message,traceId){try{await(await getConnection())`
2242
2242
  INSERT INTO mailbox (id, repo_path, "from", "to", body, trace_id, created_at)
2243
2243
  VALUES (${`mail-${traceId}`}, ${repoPath}, 'system', ${leader}, ${message}, ${traceId}, now())
2244
2244
  `}catch{try{await send(repoPath,"system",leader,message)}catch{}}}async function deliverToHierarchy(leader,teamName,message,traceId){let sql=await getConnection(),current=leader,visited=new Set([current]);for(;;){let reportsTo=(await sql`
@@ -2251,7 +2251,7 @@ ${body}`;writeFileSync17(filePath,output,"utf-8")}function serializeSdkConfig(sd
2251
2251
  AND a.team = ${teamName}
2252
2252
  AND e.state NOT IN ('terminated', 'done', 'error')
2253
2253
  LIMIT 1
2254
- `;if(rows.length>0){let provider=getProvider(rows[0].provider);if(provider?.deliverMessage)await provider.deliverMessage(rows[0].executor_id,{text:message,traceId})}}async function deliverToTeamOnce(event,teamName){let team=await getTeam(teamName);if(!team)return;let traceId=randomUUID7(),message=`[${event.eventType}] ${event.summary}`;if(event.taskId){let systemActor={actorType:"local",actorId:"system"};try{await commentOnTask(event.taskId,systemActor,message,team.repo)}catch{}}if(team.leader)await writeMailbox(team.repo,team.leader,message,traceId),await deliverViaProvider(team.leader,teamName,message,traceId),await deliverToHierarchy(team.leader,teamName,message,traceId);await publishRuntimeEvent({repoPath:team.repo,kind:"system",agent:event.agentId??"system",team:teamName,text:event.summary,source:"hook",threadId:event.taskId?`task:${event.taskId}`:`team:${teamName}`,traceId,data:{channel:event.channel,eventType:event.eventType,...event.payload}})}async function deliverToTeam2(event,teamName){if(!CRITICAL_EVENTS.has(event.eventType)){try{await deliverToTeamOnce(event,teamName)}catch{}return}for(let attempt=1;attempt<=MAX_RETRIES;attempt++)try{await deliverToTeamOnce(event,teamName);return}catch{if(attempt<MAX_RETRIES){let backoff2=BASE_BACKOFF_MS*2**(attempt-1);await new Promise((r)=>setTimeout(r,backoff2))}}}async function routeEvent(event,handler){if(handler){await handler(event);return}let targets=await resolveTargetTeams(event);for(let teamName of targets)await deliverToTeam2(event,teamName)}async function startEventRouter(handler){if(process.env.GENIE_ENABLE_EVENT_ROUTING==="false")return{stop:async()=>{}};let sql=await getConnection(),listeners=[];for(let channel of CHANNELS){let listener=await sql.listen(channel,(payload)=>{let event=parseNotifyPayload(channel,payload);if(!event)return;routeEvent(event,handler).catch(()=>{})});listeners.push(listener)}return{stop:async()=>{for(let listener of listeners)await listener.unlisten()}}}var ACTIONABLE_EVENTS,CRITICAL_EVENTS,MAX_RETRIES=3,BASE_BACKOFF_MS=500,CHANNELS;var init_event_router=__esm(()=>{init_db();init_mailbox();init_registry2();init_runtime_events();init_task_service();init_team_manager();ACTIONABLE_EVENTS=new Set(["task.blocked","executor.error","executor.permission"]),CRITICAL_EVENTS=new Set(["task.blocked","executor.error","executor.permission"]);CHANNELS=["genie_task_stage","genie_executor_state","genie_message","genie_audit_event"]});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"])});import{lstat,readdir as readdir7,realpath,stat as stat5}from"fs/promises";import{join as pjoin,relative as prelative,resolve as presolve,sep as psep}from"path";import{Readable}from"stream";function readdirp(root,options={}){let type2=options.entryType||options.type;if(type2==="both")type2=EntryTypes.FILE_DIR_TYPE;if(type2)options.type=type2;if(!root)throw Error("readdirp: root argument is required. Usage: readdirp(root, options)");else if(typeof root!=="string")throw TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");else if(type2&&!ALL_TYPES.includes(type2))throw Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(", ")}`);return options.root=root,new ReaddirpStream(options)}var EntryTypes,defaultOptions,RECURSIVE_ERROR_CODE="READDIRP_RECURSIVE_ERROR",NORMAL_FLOW_ERRORS,ALL_TYPES,DIR_TYPES,FILE_TYPES,isNormalFlowError=(error2)=>NORMAL_FLOW_ERRORS.has(error2.code),wantBigintFsStats,emptyFn=(_entryInfo)=>!0,normalizeFilter=(filter)=>{if(filter===void 0)return emptyFn;if(typeof filter==="function")return filter;if(typeof filter==="string"){let fl=filter.trim();return(entry2)=>entry2.basename===fl}if(Array.isArray(filter)){let trItems=filter.map((item)=>item.trim());return(entry2)=>trItems.some((f)=>entry2.basename===f)}return emptyFn},ReaddirpStream;var init_readdirp=__esm(()=>{EntryTypes={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},defaultOptions={root:".",fileFilter:(_entryInfo)=>!0,directoryFilter:(_entryInfo)=>!0,type:EntryTypes.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(defaultOptions);NORMAL_FLOW_ERRORS=new Set(["ENOENT","EPERM","EACCES","ELOOP",RECURSIVE_ERROR_CODE]),ALL_TYPES=[EntryTypes.DIR_TYPE,EntryTypes.EVERYTHING_TYPE,EntryTypes.FILE_DIR_TYPE,EntryTypes.FILE_TYPE],DIR_TYPES=new Set([EntryTypes.DIR_TYPE,EntryTypes.EVERYTHING_TYPE,EntryTypes.FILE_DIR_TYPE]),FILE_TYPES=new Set([EntryTypes.EVERYTHING_TYPE,EntryTypes.FILE_DIR_TYPE,EntryTypes.FILE_TYPE]),wantBigintFsStats=process.platform==="win32";ReaddirpStream=class ReaddirpStream extends Readable{parents;reading;parent;_stat;_maxDepth;_wantsDir;_wantsFile;_wantsEverything;_root;_isDirent;_statsProp;_rdOptions;_fileFilter;_directoryFilter;constructor(options={}){super({objectMode:!0,autoDestroy:!0,highWaterMark:options.highWaterMark});let opts={...defaultOptions,...options},{root,type:type2}=opts;this._fileFilter=normalizeFilter(opts.fileFilter),this._directoryFilter=normalizeFilter(opts.directoryFilter);let statMethod=opts.lstat?lstat:stat5;if(wantBigintFsStats)this._stat=(path3)=>statMethod(path3,{bigint:!0});else this._stat=statMethod;this._maxDepth=opts.depth!=null&&Number.isSafeInteger(opts.depth)?opts.depth:defaultOptions.depth,this._wantsDir=type2?DIR_TYPES.has(type2):!1,this._wantsFile=type2?FILE_TYPES.has(type2):!1,this._wantsEverything=type2===EntryTypes.EVERYTHING_TYPE,this._root=presolve(root),this._isDirent=!opts.alwaysStat,this._statsProp=this._isDirent?"dirent":"stats",this._rdOptions={encoding:"utf8",withFileTypes:this._isDirent},this.parents=[this._exploreDir(root,1)],this.reading=!1,this.parent=void 0}async _read(batch){if(this.reading)return;this.reading=!0;try{while(!this.destroyed&&batch>0){let par=this.parent,fil=par&&par.files;if(fil&&fil.length>0){let{path:path3,depth}=par,slice=fil.splice(0,batch).map((dirent)=>this._formatEntry(dirent,path3)),awaited=await Promise.all(slice);for(let entry2 of awaited){if(!entry2)continue;if(this.destroyed)return;let entryType=await this._getEntryType(entry2);if(entryType==="directory"&&this._directoryFilter(entry2)){if(depth<=this._maxDepth)this.parents.push(this._exploreDir(entry2.fullPath,depth+1));if(this._wantsDir)this.push(entry2),batch--}else if((entryType==="file"||this._includeAsFile(entry2))&&this._fileFilter(entry2)){if(this._wantsFile)this.push(entry2),batch--}}}else{let parent=this.parents.pop();if(!parent){this.push(null);break}if(this.parent=await parent,this.destroyed)return}}}catch(error2){this.destroy(error2)}finally{this.reading=!1}}async _exploreDir(path3,depth){let files;try{files=await readdir7(path3,this._rdOptions)}catch(error2){this._onError(error2)}return{files,depth,path:path3}}async _formatEntry(dirent,path3){let entry2,basename6=this._isDirent?dirent.name:dirent;try{let fullPath=presolve(pjoin(path3,basename6));entry2={path:prelative(this._root,fullPath),fullPath,basename:basename6},entry2[this._statsProp]=this._isDirent?dirent:await this._stat(fullPath)}catch(err){this._onError(err);return}return entry2}_onError(err){if(isNormalFlowError(err)&&!this.destroyed)this.emit("warn",err);else this.destroy(err)}async _getEntryType(entry2){if(!entry2&&this._statsProp in entry2)return"";let stats2=entry2[this._statsProp];if(stats2.isFile())return"file";if(stats2.isDirectory())return"directory";if(stats2&&stats2.isSymbolicLink()){let full=entry2.fullPath;try{let entryRealPath=await realpath(full),entryRealPathStats=await lstat(entryRealPath);if(entryRealPathStats.isFile())return"file";if(entryRealPathStats.isDirectory()){let len=entryRealPath.length;if(full.startsWith(entryRealPath)&&full.substr(len,1)===psep){let recursiveError=Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);return recursiveError.code=RECURSIVE_ERROR_CODE,this._onError(recursiveError)}return"directory"}}catch(error2){return this._onError(error2),""}}}_includeAsFile(entry2){let stats2=entry2&&entry2[this._statsProp];return stats2&&this._wantsEverything&&!stats2.isDirectory()}}});import{watch as fs_watch,unwatchFile,watchFile}from"fs";import{realpath as fsrealpath,lstat as lstat2,open as open4,stat as stat6}from"fs/promises";import{type as osType}from"os";import*as sp from"path";function createFsWatchInstance(path3,options,listener,errHandler,emitRaw){let handleEvent=(rawEvent,evPath)=>{if(listener(path3),emitRaw(rawEvent,evPath,{watchedPath:path3}),evPath&&path3!==evPath)fsWatchBroadcast(sp.resolve(path3,evPath),KEY_LISTENERS,sp.join(path3,evPath))};try{return fs_watch(path3,{persistent:options.persistent},handleEvent)}catch(error2){errHandler(error2);return}}class NodeFsHandler{fsw;_boundHandleError;constructor(fsW){this.fsw=fsW,this._boundHandleError=(error2)=>fsW._handleError(error2)}_watchWithNodeFs(path3,listener){let opts=this.fsw.options,directory=sp.dirname(path3),basename7=sp.basename(path3);this.fsw._getWatchedDir(directory).add(basename7);let absolutePath=sp.resolve(path3),options={persistent:opts.persistent};if(!listener)listener=EMPTY_FN;let closer;if(opts.usePolling){let enableBin=opts.interval!==opts.binaryInterval;options.interval=enableBin&&isBinaryPath(basename7)?opts.binaryInterval:opts.interval,closer=setFsWatchFileListener(path3,absolutePath,options,{listener,rawEmitter:this.fsw._emitRaw})}else closer=setFsWatchListener(path3,absolutePath,options,{listener,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return closer}_handleFile(file,stats2,initialAdd){if(this.fsw.closed)return;let dirname18=sp.dirname(file),basename7=sp.basename(file),parent=this.fsw._getWatchedDir(dirname18),prevStats=stats2;if(parent.has(basename7))return;let listener=async(path3,newStats)=>{if(!this.fsw._throttle(THROTTLE_MODE_WATCH,file,5))return;if(!newStats||newStats.mtimeMs===0)try{let newStats2=await stat6(file);if(this.fsw.closed)return;let{atimeMs:at,mtimeMs:mt}=newStats2;if(!at||at<=mt||mt!==prevStats.mtimeMs)this.fsw._emit(EV.CHANGE,file,newStats2);if((isMacos||isLinux||isFreeBSD)&&prevStats.ino!==newStats2.ino){this.fsw._closeFile(path3),prevStats=newStats2;let closer2=this._watchWithNodeFs(file,listener);if(closer2)this.fsw._addPathCloser(path3,closer2)}else prevStats=newStats2}catch(error2){this.fsw._remove(dirname18,basename7)}else if(parent.has(basename7)){let{atimeMs:at,mtimeMs:mt}=newStats;if(!at||at<=mt||mt!==prevStats.mtimeMs)this.fsw._emit(EV.CHANGE,file,newStats);prevStats=newStats}},closer=this._watchWithNodeFs(file,listener);if(!(initialAdd&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(file)){if(!this.fsw._throttle(EV.ADD,file,0))return;this.fsw._emit(EV.ADD,file,stats2)}return closer}async _handleSymlink(entry2,directory,path3,item){if(this.fsw.closed)return;let full=entry2.fullPath,dir=this.fsw._getWatchedDir(directory);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let linkPath;try{linkPath=await fsrealpath(path3)}catch(e){return this.fsw._emitReady(),!0}if(this.fsw.closed)return;if(dir.has(item)){if(this.fsw._symlinkPaths.get(full)!==linkPath)this.fsw._symlinkPaths.set(full,linkPath),this.fsw._emit(EV.CHANGE,path3,entry2.stats)}else dir.add(item),this.fsw._symlinkPaths.set(full,linkPath),this.fsw._emit(EV.ADD,path3,entry2.stats);return this.fsw._emitReady(),!0}if(this.fsw._symlinkPaths.has(full))return!0;this.fsw._symlinkPaths.set(full,!0)}_handleRead(directory,initialAdd,wh,target,dir,depth,throttler){directory=sp.join(directory,"");let throttleKey=target?`${directory}:${target}`:directory;if(throttler=this.fsw._throttle("readdir",throttleKey,1000),!throttler)return;let previous=this.fsw._getWatchedDir(wh.path),current=new Set,stream=this.fsw._readdirp(directory,{fileFilter:(entry2)=>wh.filterPath(entry2),directoryFilter:(entry2)=>wh.filterDir(entry2)});if(!stream)return;return stream.on(STR_DATA,async(entry2)=>{if(this.fsw.closed){stream=void 0;return}let item=entry2.path,path3=sp.join(directory,item);if(current.add(item),entry2.stats.isSymbolicLink()&&await this._handleSymlink(entry2,directory,path3,item))return;if(this.fsw.closed){stream=void 0;return}if(item===target||!target&&!previous.has(item))this.fsw._incrReadyCount(),path3=sp.join(dir,sp.relative(dir,path3)),this._addToNodeFs(path3,initialAdd,wh,depth+1)}).on(EV.ERROR,this._boundHandleError),new Promise((resolve10,reject)=>{if(!stream)return reject();stream.once(STR_END,()=>{if(this.fsw.closed){stream=void 0;return}let wasThrottled=throttler?throttler.clear():!1;if(resolve10(void 0),previous.getChildren().filter((item)=>{return item!==directory&&!current.has(item)}).forEach((item)=>{this.fsw._remove(directory,item)}),stream=void 0,wasThrottled)this._handleRead(directory,!1,wh,target,dir,depth,throttler)})})}async _handleDir(dir,stats2,initialAdd,depth,target,wh,realpath2){let parentDir=this.fsw._getWatchedDir(sp.dirname(dir)),tracked=parentDir.has(sp.basename(dir));if(!(initialAdd&&this.fsw.options.ignoreInitial)&&!target&&!tracked)this.fsw._emit(EV.ADD_DIR,dir,stats2);parentDir.add(sp.basename(dir)),this.fsw._getWatchedDir(dir);let throttler,closer,oDepth=this.fsw.options.depth;if((oDepth==null||depth<=oDepth)&&!this.fsw._symlinkPaths.has(realpath2)){if(!target){if(await this._handleRead(dir,initialAdd,wh,target,dir,depth,throttler),this.fsw.closed)return}closer=this._watchWithNodeFs(dir,(dirPath,stats3)=>{if(stats3&&stats3.mtimeMs===0)return;this._handleRead(dirPath,!1,wh,target,dir,depth,throttler)})}return closer}async _addToNodeFs(path3,initialAdd,priorWh,depth,target){let ready=this.fsw._emitReady;if(this.fsw._isIgnored(path3)||this.fsw.closed)return ready(),!1;let wh=this.fsw._getWatchHelpers(path3);if(priorWh)wh.filterPath=(entry2)=>priorWh.filterPath(entry2),wh.filterDir=(entry2)=>priorWh.filterDir(entry2);try{let stats2=await statMethods[wh.statMethod](wh.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(wh.watchPath,stats2))return ready(),!1;let follow=this.fsw.options.followSymlinks,closer;if(stats2.isDirectory()){let absPath=sp.resolve(path3),targetPath=follow?await fsrealpath(path3):path3;if(this.fsw.closed)return;if(closer=await this._handleDir(wh.watchPath,stats2,initialAdd,depth,target,wh,targetPath),this.fsw.closed)return;if(absPath!==targetPath&&targetPath!==void 0)this.fsw._symlinkPaths.set(absPath,targetPath)}else if(stats2.isSymbolicLink()){let targetPath=follow?await fsrealpath(path3):path3;if(this.fsw.closed)return;let parent=sp.dirname(wh.watchPath);if(this.fsw._getWatchedDir(parent).add(wh.watchPath),this.fsw._emit(EV.ADD,wh.watchPath,stats2),closer=await this._handleDir(parent,stats2,initialAdd,depth,path3,wh,targetPath),this.fsw.closed)return;if(targetPath!==void 0)this.fsw._symlinkPaths.set(sp.resolve(path3),targetPath)}else closer=this._handleFile(wh.watchPath,stats2,initialAdd);if(ready(),closer)this.fsw._addPathCloser(path3,closer);return!1}catch(error2){if(this.fsw._handleError(error2))return ready(),path3}}}var STR_DATA="data",STR_END="end",STR_CLOSE="close",EMPTY_FN=()=>{},pl,isWindows,isMacos,isLinux,isFreeBSD,isIBMi,EVENTS,EV,THROTTLE_MODE_WATCH="watch",statMethods,KEY_LISTENERS="listeners",KEY_ERR="errHandlers",KEY_RAW="rawEmitters",HANDLER_KEYS,binaryExtensions,isBinaryPath=(filePath)=>binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase()),foreach=(val,fn)=>{if(val instanceof Set)val.forEach(fn);else fn(val)},addAndConvert=(main,prop,item)=>{let container=main[prop];if(!(container instanceof Set))main[prop]=container=new Set([container]);container.add(item)},clearItem=(cont)=>(key)=>{let set2=cont[key];if(set2 instanceof Set)set2.clear();else delete cont[key]},delFromSet=(main,prop,item)=>{let container=main[prop];if(container instanceof Set)container.delete(item);else if(container===item)delete main[prop]},isEmptySet=(val)=>val instanceof Set?val.size===0:!val,FsWatchInstances,fsWatchBroadcast=(fullPath,listenerType,val1,val2,val3)=>{let cont=FsWatchInstances.get(fullPath);if(!cont)return;foreach(cont[listenerType],(listener)=>{listener(val1,val2,val3)})},setFsWatchListener=(path3,fullPath,options,handlers)=>{let{listener,errHandler,rawEmitter}=handlers,cont=FsWatchInstances.get(fullPath),watcher;if(!options.persistent){if(watcher=createFsWatchInstance(path3,options,listener,errHandler,rawEmitter),!watcher)return;return watcher.close.bind(watcher)}if(cont)addAndConvert(cont,KEY_LISTENERS,listener),addAndConvert(cont,KEY_ERR,errHandler),addAndConvert(cont,KEY_RAW,rawEmitter);else{if(watcher=createFsWatchInstance(path3,options,fsWatchBroadcast.bind(null,fullPath,KEY_LISTENERS),errHandler,fsWatchBroadcast.bind(null,fullPath,KEY_RAW)),!watcher)return;watcher.on(EV.ERROR,async(error2)=>{let broadcastErr=fsWatchBroadcast.bind(null,fullPath,KEY_ERR);if(cont)cont.watcherUnusable=!0;if(isWindows&&error2.code==="EPERM")try{await(await open4(path3,"r")).close(),broadcastErr(error2)}catch(err){}else broadcastErr(error2)}),cont={listeners:listener,errHandlers:errHandler,rawEmitters:rawEmitter,watcher},FsWatchInstances.set(fullPath,cont)}return()=>{if(delFromSet(cont,KEY_LISTENERS,listener),delFromSet(cont,KEY_ERR,errHandler),delFromSet(cont,KEY_RAW,rawEmitter),isEmptySet(cont.listeners))cont.watcher.close(),FsWatchInstances.delete(fullPath),HANDLER_KEYS.forEach(clearItem(cont)),cont.watcher=void 0,Object.freeze(cont)}},FsWatchFileInstances,setFsWatchFileListener=(path3,fullPath,options,handlers)=>{let{listener,rawEmitter}=handlers,cont=FsWatchFileInstances.get(fullPath),copts=cont&&cont.options;if(copts&&(copts.persistent<options.persistent||copts.interval>options.interval))unwatchFile(fullPath),cont=void 0;if(cont)addAndConvert(cont,KEY_LISTENERS,listener),addAndConvert(cont,KEY_RAW,rawEmitter);else cont={listeners:listener,rawEmitters:rawEmitter,options,watcher:watchFile(fullPath,options,(curr,prev)=>{foreach(cont.rawEmitters,(rawEmitter2)=>{rawEmitter2(EV.CHANGE,fullPath,{curr,prev})});let currmtime=curr.mtimeMs;if(curr.size!==prev.size||currmtime>prev.mtimeMs||currmtime===0)foreach(cont.listeners,(listener2)=>listener2(path3,curr))})},FsWatchFileInstances.set(fullPath,cont);return()=>{if(delFromSet(cont,KEY_LISTENERS,listener),delFromSet(cont,KEY_RAW,rawEmitter),isEmptySet(cont.listeners))FsWatchFileInstances.delete(fullPath),unwatchFile(fullPath),cont.options=cont.watcher=void 0,Object.freeze(cont)}};var init_handler=__esm(()=>{pl=process.platform,isWindows=pl==="win32",isMacos=pl==="darwin",isLinux=pl==="linux",isFreeBSD=pl==="freebsd",isIBMi=osType()==="OS400",EVENTS={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},EV=EVENTS,statMethods={lstat:lstat2,stat:stat6},HANDLER_KEYS=[KEY_LISTENERS,KEY_ERR,KEY_RAW],binaryExtensions=new Set(["3dm","3ds","3g2","3gp","7z","a","aac","adp","afdesign","afphoto","afpub","ai","aif","aiff","alz","ape","apk","appimage","ar","arj","asf","au","avi","bak","baml","bh","bin","bk","bmp","btif","bz2","bzip2","cab","caf","cgm","class","cmx","cpio","cr2","cur","dat","dcm","deb","dex","djvu","dll","dmg","dng","doc","docm","docx","dot","dotm","dra","DS_Store","dsk","dts","dtshd","dvb","dwg","dxf","ecelp4800","ecelp7470","ecelp9600","egg","eol","eot","epub","exe","f4v","fbs","fh","fla","flac","flatpak","fli","flv","fpx","fst","fvt","g3","gh","gif","graffle","gz","gzip","h261","h263","h264","icns","ico","ief","img","ipa","iso","jar","jpeg","jpg","jpgv","jpm","jxr","key","ktx","lha","lib","lvp","lz","lzh","lzma","lzo","m3u","m4a","m4v","mar","mdi","mht","mid","midi","mj2","mka","mkv","mmr","mng","mobi","mov","movie","mp3","mp4","mp4a","mpeg","mpg","mpga","mxu","nef","npx","numbers","nupkg","o","odp","ods","odt","oga","ogg","ogv","otf","ott","pages","pbm","pcx","pdb","pdf","pea","pgm","pic","png","pnm","pot","potm","potx","ppa","ppam","ppm","pps","ppsm","ppsx","ppt","pptm","pptx","psd","pya","pyc","pyo","pyv","qt","rar","ras","raw","resources","rgb","rip","rlc","rmf","rmvb","rpm","rtf","rz","s3m","s7z","scpt","sgi","shar","snap","sil","sketch","slk","smv","snk","so","stl","suo","sub","swf","tar","tbz","tbz2","tga","tgz","thmx","tif","tiff","tlz","ttc","ttf","txz","udf","uvh","uvi","uvm","uvp","uvs","uvu","viv","vob","war","wav","wax","wbmp","wdp","weba","webm","webp","whl","wim","wm","wma","wmv","wmx","woff","woff2","wrm","wvx","xbm","xif","xla","xlam","xls","xlsb","xlsm","xlsx","xlt","xltm","xltx","xm","xmind","xpi","xpm","xwd","xz","z","zip","zipx"]),FsWatchInstances=new Map;FsWatchFileInstances=new Map});import{EventEmitter}from"events";import{stat as statcb,Stats}from"fs";import{readdir as readdir8,stat as stat7}from"fs/promises";import*as sp2 from"path";function arrify(item){return Array.isArray(item)?item:[item]}function createPattern(matcher){if(typeof matcher==="function")return matcher;if(typeof matcher==="string")return(string)=>matcher===string;if(matcher instanceof RegExp)return(string)=>matcher.test(string);if(typeof matcher==="object"&&matcher!==null)return(string)=>{if(matcher.path===string)return!0;if(matcher.recursive){let relative4=sp2.relative(matcher.path,string);if(!relative4)return!1;return!relative4.startsWith("..")&&!sp2.isAbsolute(relative4)}return!1};return()=>!1}function normalizePath(path3){if(typeof path3!=="string")throw Error("string expected");path3=sp2.normalize(path3),path3=path3.replace(/\\/g,"/");let prepend=!1;if(path3.startsWith("//"))prepend=!0;if(path3=path3.replace(DOUBLE_SLASH_RE,"/"),prepend)path3="/"+path3;return path3}function matchPatterns2(patterns2,testString,stats2){let path3=normalizePath(testString);for(let index=0;index<patterns2.length;index++){let pattern=patterns2[index];if(pattern(path3,stats2))return!0}return!1}function anymatch(matchers,testString){if(matchers==null)throw TypeError("anymatch: specify first argument");let patterns2=arrify(matchers).map((matcher)=>createPattern(matcher));if(testString==null)return(testString2,stats2)=>{return matchPatterns2(patterns2,testString2,stats2)};return matchPatterns2(patterns2,testString)}class DirEntry{path;_removeWatcher;items;constructor(dir,removeWatcher){this.path=dir,this._removeWatcher=removeWatcher,this.items=new Set}add(item){let{items}=this;if(!items)return;if(item!==ONE_DOT&&item!==TWO_DOTS)items.add(item)}async remove(item){let{items}=this;if(!items)return;if(items.delete(item),items.size>0)return;let dir=this.path;try{await readdir8(dir)}catch(err){if(this._removeWatcher)this._removeWatcher(sp2.dirname(dir),sp2.basename(dir))}}has(item){let{items}=this;if(!items)return;return items.has(item)}getChildren(){let{items}=this;if(!items)return[];return[...items.values()]}dispose(){this.items.clear(),this.path="",this._removeWatcher=EMPTY_FN,this.items=EMPTY_SET,Object.freeze(this)}}class WatchHelper{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(path3,follow,fsw){this.fsw=fsw;let watchPath=path3;this.path=path3=path3.replace(REPLACER_RE,""),this.watchPath=watchPath,this.fullWatchPath=sp2.resolve(watchPath),this.dirParts=[],this.dirParts.forEach((parts)=>{if(parts.length>1)parts.pop()}),this.followSymlinks=follow,this.statMethod=follow?STAT_METHOD_F:STAT_METHOD_L}entryPath(entry2){return sp2.join(this.watchPath,sp2.relative(this.watchPath,entry2.fullPath))}filterPath(entry2){let{stats:stats2}=entry2;if(stats2&&stats2.isSymbolicLink())return this.filterDir(entry2);let resolvedPath=this.entryPath(entry2);return this.fsw._isntIgnored(resolvedPath,stats2)&&this.fsw._hasReadPermissions(stats2)}filterDir(entry2){return this.fsw._isntIgnored(this.entryPath(entry2),entry2.stats)}}function watch(paths,options={}){let watcher=new FSWatcher(options);return watcher.add(paths),watcher}var SLASH="/",SLASH_SLASH="//",ONE_DOT=".",TWO_DOTS="..",STRING_TYPE="string",BACK_SLASH_RE,DOUBLE_SLASH_RE,DOT_RE,REPLACER_RE,isMatcherObject=(matcher)=>typeof matcher==="object"&&matcher!==null&&!(matcher instanceof RegExp),unifyPaths=(paths_)=>{let paths=arrify(paths_).flat();if(!paths.every((p)=>typeof p===STRING_TYPE))throw TypeError(`Non-string provided as watch path: ${paths}`);return paths.map(normalizePathToUnix)},toUnix=(string)=>{let str3=string.replace(BACK_SLASH_RE,SLASH),prepend=!1;if(str3.startsWith(SLASH_SLASH))prepend=!0;if(str3=str3.replace(DOUBLE_SLASH_RE,SLASH),prepend)str3=SLASH+str3;return str3},normalizePathToUnix=(path3)=>toUnix(sp2.normalize(toUnix(path3))),normalizeIgnored=(cwd="")=>(path3)=>{if(typeof path3==="string")return normalizePathToUnix(sp2.isAbsolute(path3)?path3:sp2.join(cwd,path3));else return path3},getAbsolutePath=(path3,cwd)=>{if(sp2.isAbsolute(path3))return path3;return sp2.join(cwd,path3)},EMPTY_SET,STAT_METHOD_F="stat",STAT_METHOD_L="lstat",FSWatcher;var init_chokidar=__esm(()=>{init_readdirp();init_handler();/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */BACK_SLASH_RE=/\\/g,DOUBLE_SLASH_RE=/\/\//g,DOT_RE=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,REPLACER_RE=/^\.[/\\]/;EMPTY_SET=Object.freeze(new Set);FSWatcher=class FSWatcher extends EventEmitter{closed;options;_closers;_ignoredPaths;_throttled;_streams;_symlinkPaths;_watched;_pendingWrites;_pendingUnlinks;_readyCount;_emitReady;_closePromise;_userIgnored;_readyEmitted;_emitRaw;_boundRemove;_nodeFsHandler;constructor(_opts={}){super();this.closed=!1,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._streams=new Set,this._symlinkPaths=new Map,this._watched=new Map,this._pendingWrites=new Map,this._pendingUnlinks=new Map,this._readyCount=0,this._readyEmitted=!1;let awf=_opts.awaitWriteFinish,DEF_AWF={stabilityThreshold:2000,pollInterval:100},opts={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,..._opts,ignored:_opts.ignored?arrify(_opts.ignored):arrify([]),awaitWriteFinish:awf===!0?DEF_AWF:typeof awf==="object"?{...DEF_AWF,...awf}:!1};if(isIBMi)opts.usePolling=!0;if(opts.atomic===void 0)opts.atomic=!opts.usePolling;let envPoll=process.env.CHOKIDAR_USEPOLLING;if(envPoll!==void 0){let envLower=envPoll.toLowerCase();if(envLower==="false"||envLower==="0")opts.usePolling=!1;else if(envLower==="true"||envLower==="1")opts.usePolling=!0;else opts.usePolling=!!envLower}let envInterval=process.env.CHOKIDAR_INTERVAL;if(envInterval)opts.interval=Number.parseInt(envInterval,10);let readyCalls=0;this._emitReady=()=>{if(readyCalls++,readyCalls>=this._readyCount)this._emitReady=EMPTY_FN,this._readyEmitted=!0,process.nextTick(()=>this.emit(EVENTS.READY))},this._emitRaw=(...args)=>this.emit(EVENTS.RAW,...args),this._boundRemove=this._remove.bind(this),this.options=opts,this._nodeFsHandler=new NodeFsHandler(this),Object.freeze(opts)}_addIgnoredPath(matcher){if(isMatcherObject(matcher)){for(let ignored of this._ignoredPaths)if(isMatcherObject(ignored)&&ignored.path===matcher.path&&ignored.recursive===matcher.recursive)return}this._ignoredPaths.add(matcher)}_removeIgnoredPath(matcher){if(this._ignoredPaths.delete(matcher),typeof matcher==="string"){for(let ignored of this._ignoredPaths)if(isMatcherObject(ignored)&&ignored.path===matcher)this._ignoredPaths.delete(ignored)}}add(paths_,_origAdd,_internal){let{cwd}=this.options;this.closed=!1,this._closePromise=void 0;let paths=unifyPaths(paths_);if(cwd)paths=paths.map((path3)=>{return getAbsolutePath(path3,cwd)});if(paths.forEach((path3)=>{this._removeIgnoredPath(path3)}),this._userIgnored=void 0,!this._readyCount)this._readyCount=0;return this._readyCount+=paths.length,Promise.all(paths.map(async(path3)=>{let res=await this._nodeFsHandler._addToNodeFs(path3,!_internal,void 0,0,_origAdd);if(res)this._emitReady();return res})).then((results)=>{if(this.closed)return;results.forEach((item)=>{if(item)this.add(sp2.dirname(item),sp2.basename(_origAdd||item))})}),this}unwatch(paths_){if(this.closed)return this;let paths=unifyPaths(paths_),{cwd}=this.options;return paths.forEach((path3)=>{if(!sp2.isAbsolute(path3)&&!this._closers.has(path3)){if(cwd)path3=sp2.join(cwd,path3);path3=sp2.resolve(path3)}if(this._closePath(path3),this._addIgnoredPath(path3),this._watched.has(path3))this._addIgnoredPath({path:path3,recursive:!0});this._userIgnored=void 0}),this}close(){if(this._closePromise)return this._closePromise;this.closed=!0,this.removeAllListeners();let closers=[];return this._closers.forEach((closerList)=>closerList.forEach((closer)=>{let promise=closer();if(promise instanceof Promise)closers.push(promise)})),this._streams.forEach((stream)=>stream.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=!1,this._watched.forEach((dirent)=>dirent.dispose()),this._closers.clear(),this._watched.clear(),this._streams.clear(),this._symlinkPaths.clear(),this._throttled.clear(),this._closePromise=closers.length?Promise.all(closers).then(()=>{return}):Promise.resolve(),this._closePromise}getWatched(){let watchList={};return this._watched.forEach((entry2,dir)=>{let index=(this.options.cwd?sp2.relative(this.options.cwd,dir):dir)||ONE_DOT;watchList[index]=entry2.getChildren().sort()}),watchList}emitWithAll(event,args){if(this.emit(event,...args),event!==EVENTS.ERROR)this.emit(EVENTS.ALL,event,...args)}async _emit(event,path3,stats2){if(this.closed)return;let opts=this.options;if(isWindows)path3=sp2.normalize(path3);if(opts.cwd)path3=sp2.relative(opts.cwd,path3);let args=[path3];if(stats2!=null)args.push(stats2);let awf=opts.awaitWriteFinish,pw;if(awf&&(pw=this._pendingWrites.get(path3)))return pw.lastChange=new Date,this;if(opts.atomic){if(event===EVENTS.UNLINK)return this._pendingUnlinks.set(path3,[event,...args]),setTimeout(()=>{this._pendingUnlinks.forEach((entry2,path4)=>{this.emit(...entry2),this.emit(EVENTS.ALL,...entry2),this._pendingUnlinks.delete(path4)})},typeof opts.atomic==="number"?opts.atomic:100),this;if(event===EVENTS.ADD&&this._pendingUnlinks.has(path3))event=EVENTS.CHANGE,this._pendingUnlinks.delete(path3)}if(awf&&(event===EVENTS.ADD||event===EVENTS.CHANGE)&&this._readyEmitted){let awfEmit=(err,stats3)=>{if(err)event=EVENTS.ERROR,args[0]=err,this.emitWithAll(event,args);else if(stats3){if(args.length>1)args[1]=stats3;else args.push(stats3);this.emitWithAll(event,args)}};return this._awaitWriteFinish(path3,awf.stabilityThreshold,event,awfEmit),this}if(event===EVENTS.CHANGE){if(!this._throttle(EVENTS.CHANGE,path3,50))return this}if(opts.alwaysStat&&stats2===void 0&&(event===EVENTS.ADD||event===EVENTS.ADD_DIR||event===EVENTS.CHANGE)){let fullPath=opts.cwd?sp2.join(opts.cwd,path3):path3,stats3;try{stats3=await stat7(fullPath)}catch(err){}if(!stats3||this.closed)return;args.push(stats3)}return this.emitWithAll(event,args),this}_handleError(error2){let code=error2&&error2.code;if(error2&&code!=="ENOENT"&&code!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||code!=="EPERM"&&code!=="EACCES"))this.emit(EVENTS.ERROR,error2);return error2||this.closed}_throttle(actionType,path3,timeout){if(!this._throttled.has(actionType))this._throttled.set(actionType,new Map);let action=this._throttled.get(actionType);if(!action)throw Error("invalid throttle");let actionPath=action.get(path3);if(actionPath)return actionPath.count++,!1;let timeoutObject,clear=()=>{let item=action.get(path3),count=item?item.count:0;if(action.delete(path3),clearTimeout(timeoutObject),item)clearTimeout(item.timeoutObject);return count};timeoutObject=setTimeout(clear,timeout);let thr={timeoutObject,clear,count:0};return action.set(path3,thr),thr}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(path3,threshold,event,awfEmit){let awf=this.options.awaitWriteFinish;if(typeof awf!=="object")return;let pollInterval=awf.pollInterval,timeoutHandler,fullPath=path3;if(this.options.cwd&&!sp2.isAbsolute(path3))fullPath=sp2.join(this.options.cwd,path3);let now=new Date,writes=this._pendingWrites;function awaitWriteFinishFn(prevStat){statcb(fullPath,(err,curStat)=>{if(err||!writes.has(path3)){if(err&&err.code!=="ENOENT")awfEmit(err);return}let now2=Number(new Date);if(prevStat&&curStat.size!==prevStat.size)writes.get(path3).lastChange=now2;let pw=writes.get(path3);if(now2-pw.lastChange>=threshold)writes.delete(path3),awfEmit(void 0,curStat);else timeoutHandler=setTimeout(awaitWriteFinishFn,pollInterval,curStat)})}if(!writes.has(path3))writes.set(path3,{lastChange:now,cancelWait:()=>{return writes.delete(path3),clearTimeout(timeoutHandler),event}}),timeoutHandler=setTimeout(awaitWriteFinishFn,pollInterval)}_isIgnored(path3,stats2){if(this.options.atomic&&DOT_RE.test(path3))return!0;if(!this._userIgnored){let{cwd}=this.options,ignored=(this.options.ignored||[]).map(normalizeIgnored(cwd)),list2=[...[...this._ignoredPaths].map(normalizeIgnored(cwd)),...ignored];this._userIgnored=anymatch(list2,void 0)}return this._userIgnored(path3,stats2)}_isntIgnored(path3,stat8){return!this._isIgnored(path3,stat8)}_getWatchHelpers(path3){return new WatchHelper(path3,this.options.followSymlinks,this)}_getWatchedDir(directory){let dir=sp2.resolve(directory);if(!this._watched.has(dir))this._watched.set(dir,new DirEntry(dir,this._boundRemove));return this._watched.get(dir)}_hasReadPermissions(stats2){if(this.options.ignorePermissionErrors)return!0;return Boolean(Number(stats2.mode)&256)}_remove(directory,item,isDirectory){let path3=sp2.join(directory,item),fullPath=sp2.resolve(path3);if(isDirectory=isDirectory!=null?isDirectory:this._watched.has(path3)||this._watched.has(fullPath),!this._throttle("remove",path3,100))return;if(!isDirectory&&this._watched.size===1)this.add(directory,item,!0);this._getWatchedDir(path3).getChildren().forEach((nested)=>this._remove(path3,nested));let parent=this._getWatchedDir(directory),wasTracked=parent.has(item);if(parent.remove(item),this._symlinkPaths.has(fullPath))this._symlinkPaths.delete(fullPath);let relPath=path3;if(this.options.cwd)relPath=sp2.relative(this.options.cwd,path3);if(this.options.awaitWriteFinish&&this._pendingWrites.has(relPath)){if(this._pendingWrites.get(relPath).cancelWait()===EVENTS.ADD)return}this._watched.delete(path3),this._watched.delete(fullPath);let eventName=isDirectory?EVENTS.UNLINK_DIR:EVENTS.UNLINK;if(wasTracked&&!this._isIgnored(path3))this._emit(eventName,path3);this._closePath(path3)}_closePath(path3){this._closeFile(path3);let dir=sp2.dirname(path3);this._getWatchedDir(dir).remove(sp2.basename(path3))}_closeFile(path3){let closers=this._closers.get(path3);if(!closers)return;closers.forEach((closer)=>closer()),this._closers.delete(path3)}_addPathCloser(path3,closer){if(!closer)return;let list2=this._closers.get(path3);if(!list2)list2=[],this._closers.set(path3,list2);list2.push(closer)}_readdirp(root,opts){if(this.closed)return;let options={type:EVENTS.ALL,alwaysStat:!0,lstat:!0,...opts,depth:0},stream=readdirp(root,options);return this._streams.add(stream),stream.once(STR_CLOSE,()=>{stream=void 0}),stream.once(STR_END,()=>{if(stream)this._streams.delete(stream),stream=void 0}),stream}}});var exports_session_filewatch={};__export(exports_session_filewatch,{stopFilewatch:()=>stopFilewatch,startFilewatch:()=>startFilewatch,resetUnrecoverableSessions:()=>resetUnrecoverableSessions,isTransientPgConnectionError:()=>isTransientPgConnectionError,isForeignKeyViolation:()=>isForeignKeyViolation,handleFileChange:()=>handleFileChange,extractSessionInfo:()=>extractSessionInfo,createJsonlWatcher:()=>createJsonlWatcher});import{homedir as homedir37}from"os";import{basename as basename8,isAbsolute as isAbsolute4,join as join58,resolve as resolve11}from"path";function resetUnrecoverableSessions(){unrecoverableSessions.clear(),offsetCache.clear()}function isForeignKeyViolation(err){if(!err||typeof err!=="object")return!1;let code=err.code;if(typeof code==="string"&&code==="23503")return!0;return(err instanceof Error?err.message:String(err)).toLowerCase().includes("foreign key constraint")}function isTransientPgConnectionError(err){if(!err||typeof err!=="object")return!1;let code=err.code;if(typeof code==="string"&&["CONNECTION_ENDED","CONNECTION_DESTROYED","CONNECT_TIMEOUT","ECONNRESET","EPIPE"].includes(code))return!0;let message=err instanceof Error?err.message:String(err);return/CONNECTION_ENDED|CONNECTION_DESTROYED|CONNECT_TIMEOUT|ECONNRESET|EPIPE|connection terminated|connection closed|server closed the connection/i.test(message)}async function loadOffsets(sql){try{let rows=await sql`SELECT id, last_ingested_offset FROM sessions WHERE last_ingested_offset > 0`;for(let row2 of rows)offsetCache.set(row2.id,row2.last_ingested_offset)}catch{}}function extractSessionInfo(filePath){if(!filePath.endsWith(".jsonl"))return null;let sessionId=basename8(filePath,".jsonl"),parts=filePath.split("/"),sessionsIdx=parts.lastIndexOf("sessions"),subagentsIdx=parts.lastIndexOf("subagents");if(subagentsIdx>0&&parts[subagentsIdx-1]){let parentSessionId=parts[subagentsIdx-1],projectIdx2=parts.indexOf("projects"),projectPath=projectIdx2>=0?parts.slice(0,projectIdx2+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}}let projectIdx=parts.lastIndexOf("projects");if(projectIdx>=0&&parts.length===projectIdx+3){let projectPath=parts.slice(0,projectIdx+2).join("/");return{sessionId,projectPath,parentSessionId:null,isSubagent:!1}}return null}async function ingestFileChange(sql,info,filePath,storedOffset,deps){let workerMap=await deps.buildWorkerMap(sql);return(await deps.ingestFileFull(sql,info.sessionId,filePath,info.projectPath,storedOffset,{parentSessionId:info.parentSessionId,isSubagent:info.isSubagent,workerMap})).newOffset}function markSessionUnrecoverable(info,filePath,message,deps){unrecoverableSessions.add(info.sessionId),offsetCache.set(info.sessionId,Number.POSITIVE_INFINITY),deps.logError(`[filewatch] skipping ${filePath} \u2014 FK constraint violation (orphan session, parent not registered): ${message}`)}async function reconnectAfterTransientPgError(err,deps){if(!isTransientPgConnectionError(err)||!deps.getConnection||!deps.resetConnection)return null;try{return await deps.resetConnection(),await deps.getConnection()}catch{return null}}async function tryIngestFileChange(sql,info,filePath,storedOffset,deps){try{return{ok:!0,newOffset:await ingestFileChange(sql,info,filePath,storedOffset,deps)}}catch(err){return{ok:!1,error:err}}}function recordIngestFailure(err,info,filePath,storedOffset,deps){let message=err instanceof Error?err.message:String(err);if(isForeignKeyViolation(err)){markSessionUnrecoverable(info,filePath,message,deps);return}deps.logError(`[filewatch] error ingesting ${filePath} at offset ${storedOffset}: ${message}`)}async function ingestWithOneReconnect(sql,info,filePath,storedOffset,deps){let first=await tryIngestFileChange(sql,info,filePath,storedOffset,deps);if(first.ok){offsetCache.set(info.sessionId,first.newOffset);return}let freshSql=await reconnectAfterTransientPgError(first.error,deps);if(!freshSql){recordIngestFailure(first.error,info,filePath,storedOffset,deps);return}let second=await tryIngestFileChange(freshSql,info,filePath,storedOffset,deps);if(second.ok)offsetCache.set(info.sessionId,second.newOffset);else recordIngestFailure(second.error,info,filePath,storedOffset,deps)}async function handleFileChange(filePath,sql,deps=defaultDeps4){let info=extractSessionInfo(filePath);if(!info)return;if(unrecoverableSessions.has(info.sessionId))return;let storedOffset=offsetCache.get(info.sessionId)??0;try{deps.setLiveWorkPending(!0),await ingestWithOneReconnect(sql,info,filePath,storedOffset,deps)}finally{deps.setLiveWorkPending(!1)}}function shouldIgnoreWatchPath(path3,stats2){return stats2?.isFile()===!0&&!path3.endsWith(".jsonl")}function normalizeWatchEventPath(claudeDir,filePath){return isAbsolute4(filePath)?filePath:resolve11(claudeDir,filePath)}function scheduleFileChange(filePath){if(!filePath.endsWith(".jsonl"))return;let existing=debounceTimers.get(filePath);if(existing)clearTimeout(existing);debounceTimers.set(filePath,setTimeout(()=>{debounceTimers.delete(filePath),getConnection().then((freshSql)=>handleFileChange(filePath,freshSql)).catch((err)=>{let message=err instanceof Error?err.message:String(err);console.error(`[filewatch] unhandled error for ${filePath}: ${message}`)})},DEBOUNCE_MS))}function createJsonlWatcher(claudeDir,onJsonlChange){let jsonlWatcher=watch(claudeDir,{ignoreInitial:!0,depth:WATCH_DEPTH,ignored:shouldIgnoreWatchPath,awaitWriteFinish:{stabilityThreshold:DEBOUNCE_MS,pollInterval:100},atomic:!0}),emitJsonlChange=(filePath)=>{if(!filePath.endsWith(".jsonl"))return;onJsonlChange(normalizeWatchEventPath(claudeDir,filePath))};return jsonlWatcher.on("add",emitJsonlChange),jsonlWatcher.on("change",emitJsonlChange),jsonlWatcher}async function startFilewatch(sql){if(watcher)return!0;let claudeDir=join58(process.env.CLAUDE_CONFIG_DIR??join58(homedir37(),".claude"),"projects");await loadOffsets(sql);try{return watcher=createJsonlWatcher(claudeDir,(fullPath)=>scheduleFileChange(fullPath)),watcher.on("error",(err)=>{let message=err instanceof Error?err.message:String(err);console.error("[filewatch] watcher error:",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,WATCH_DEPTH=4,unrecoverableSessions,defaultDeps4;var init_session_filewatch=__esm(()=>{init_chokidar();init_db();init_session_capture();offsetCache=new Map,debounceTimers=new Map,unrecoverableSessions=new Set;defaultDeps4={buildWorkerMap,ingestFileFull,setLiveWorkPending,logError:(msg)=>console.error(msg),getConnection,resetConnection}});var exports_scheduler_daemon={};__export(exports_scheduler_daemon,{terminalizeCleanExitUnverified:()=>terminalizeCleanExitUnverified,startDaemon:()=>startDaemon,runBootPass:()=>runBootPass,runAgentRecoveryPass:()=>runAgentRecoveryPass,recoverOnStartup:()=>recoverOnStartup,reconcileUnresumable:()=>reconcileUnresumable,reconcileOrphans:()=>reconcileOrphans,reconcileOrphanedRuns:()=>reconcileOrphanedRuns,reclaimExpiredLeases:()=>reclaimExpiredLeases,processMailboxRetryMessage:()=>processMailboxRetryMessage,logToFile:()=>logToFile,logReconcilerMode:()=>logReconcilerMode,isTurnAwareReconcilerEnabled:()=>isTurnAwareReconcilerEnabled,fireTrigger:()=>fireTrigger,emitWorkerEvents:()=>emitWorkerEvents,collectMachineSnapshot:()=>collectMachineSnapshot,collectHeartbeats:()=>collectHeartbeats,claimDueTriggers:()=>claimDueTriggers,attemptAgentResume:()=>attemptAgentResume,_resetWorkerStatesForTesting:()=>_resetWorkerStatesForTesting,TURN_AWARE_RECONCILER_FLAG:()=>TURN_AWARE_RECONCILER_FLAG,MAX_DELIVERY_ATTEMPTS:()=>MAX_DELIVERY_ATTEMPTS,ESCALATION_RECIPIENT:()=>ESCALATION_RECIPIENT});import{randomUUID as randomUUID8}from"crypto";import{appendFileSync as appendFileSync4,mkdirSync as mkdirSync20}from"fs";import{homedir as homedir38}from"os";import{join as join59}from"path";function isTurnAwareReconcilerEnabled(env=process.env){let raw=env[TURN_AWARE_RECONCILER_FLAG];if(raw===void 0)return!0;let v=raw.trim().toLowerCase();if(v==="")return!0;if(v==="0"||v==="false"||v==="no")return!1;if(v==="1"||v==="true"||v==="yes")return!0;return!0}function logReconcilerMode(deps,daemonId){let enabled=isTurnAwareReconcilerEnabled();deps.log({timestamp:deps.now().toISOString(),level:"info",event:enabled?"reconciler_mode_turn_aware":"reconciler_mode_legacy",daemon_id:daemonId,flag:TURN_AWARE_RECONCILER_FLAG,enabled,message:enabled?"turn-aware reconciler enabled":"flag off, using legacy reconciler"})}function getLogDir2(){return join59(process.env.GENIE_HOME??join59(homedir38(),".genie"),"logs")}function getLogFile(){return join59(getLogDir2(),"scheduler.log")}function logToFile(entry2){let logDir=getLogDir2();mkdirSync20(logDir,{recursive:!0});let enriched=entry2.trace_id?entry2:withAmbientTraceId(entry2);appendFileSync4(getLogFile(),`${JSON.stringify(enriched)}
2254
+ `;if(rows.length>0){let provider=getProvider(rows[0].provider);if(provider?.deliverMessage)await provider.deliverMessage(rows[0].executor_id,{text:message,traceId})}}async function deliverToTeamOnce(event,teamName){let team=await getTeam(teamName);if(!team)return;let traceId=randomUUID7(),message=`[${event.eventType}] ${event.summary}`;if(event.taskId){let systemActor={actorType:"local",actorId:"system"};try{await commentOnTask(event.taskId,systemActor,message,team.repo)}catch{}}if(team.leader)await writeMailbox(team.repo,team.leader,message,traceId),await deliverViaProvider(team.leader,teamName,message,traceId),await deliverToHierarchy(team.leader,teamName,message,traceId);await publishRuntimeEvent({repoPath:team.repo,kind:"system",agent:event.agentId??"system",team:teamName,text:event.summary,source:"hook",threadId:event.taskId?`task:${event.taskId}`:`team:${teamName}`,traceId,data:{channel:event.channel,eventType:event.eventType,...event.payload}})}async function deliverToTeam2(event,teamName){if(!CRITICAL_EVENTS.has(event.eventType)){try{await deliverToTeamOnce(event,teamName)}catch{}return}for(let attempt=1;attempt<=MAX_RETRIES;attempt++)try{await deliverToTeamOnce(event,teamName);return}catch{if(attempt<MAX_RETRIES){let backoff2=BASE_BACKOFF_MS*2**(attempt-1);await new Promise((r)=>setTimeout(r,backoff2))}}}async function routeEvent(event,handler){if(handler){await handler(event);return}let targets=await resolveTargetTeams(event);for(let teamName of targets)await deliverToTeam2(event,teamName)}async function startEventRouter(handler){if(process.env.GENIE_ENABLE_EVENT_ROUTING==="false")return{stop:async()=>{}};let sql=await getConnection(),listeners=[];for(let channel of CHANNELS){let listener=await sql.listen(channel,(payload)=>{let event=parseNotifyPayload(channel,payload);if(!event)return;routeEvent(event,handler).catch(()=>{})});listeners.push(listener)}return{stop:async()=>{for(let listener of listeners)await listener.unlisten()}}}var ACTIONABLE_EVENTS,CRITICAL_EVENTS,MAX_RETRIES=3,BASE_BACKOFF_MS=500,CHANNELS;var init_event_router=__esm(()=>{init_db();init_mailbox();init_registry2();init_runtime_events();init_task_service();init_team_manager();ACTIONABLE_EVENTS=new Set(["task.blocked","executor.error","executor.permission"]),CRITICAL_EVENTS=new Set(["task.blocked","executor.error","executor.permission"]);CHANNELS=["genie_task_stage","genie_executor_state","genie_message","genie_audit_event"]});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"])});import{lstat,readdir as readdir7,realpath,stat as stat5}from"fs/promises";import{join as pjoin,relative as prelative,resolve as presolve,sep as psep}from"path";import{Readable}from"stream";function readdirp(root,options={}){let type2=options.entryType||options.type;if(type2==="both")type2=EntryTypes.FILE_DIR_TYPE;if(type2)options.type=type2;if(!root)throw Error("readdirp: root argument is required. Usage: readdirp(root, options)");else if(typeof root!=="string")throw TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");else if(type2&&!ALL_TYPES.includes(type2))throw Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(", ")}`);return options.root=root,new ReaddirpStream(options)}var EntryTypes,defaultOptions,RECURSIVE_ERROR_CODE="READDIRP_RECURSIVE_ERROR",NORMAL_FLOW_ERRORS,ALL_TYPES,DIR_TYPES,FILE_TYPES,isNormalFlowError=(error2)=>NORMAL_FLOW_ERRORS.has(error2.code),wantBigintFsStats,emptyFn=(_entryInfo)=>!0,normalizeFilter=(filter)=>{if(filter===void 0)return emptyFn;if(typeof filter==="function")return filter;if(typeof filter==="string"){let fl=filter.trim();return(entry2)=>entry2.basename===fl}if(Array.isArray(filter)){let trItems=filter.map((item)=>item.trim());return(entry2)=>trItems.some((f)=>entry2.basename===f)}return emptyFn},ReaddirpStream;var init_readdirp=__esm(()=>{EntryTypes={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},defaultOptions={root:".",fileFilter:(_entryInfo)=>!0,directoryFilter:(_entryInfo)=>!0,type:EntryTypes.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(defaultOptions);NORMAL_FLOW_ERRORS=new Set(["ENOENT","EPERM","EACCES","ELOOP",RECURSIVE_ERROR_CODE]),ALL_TYPES=[EntryTypes.DIR_TYPE,EntryTypes.EVERYTHING_TYPE,EntryTypes.FILE_DIR_TYPE,EntryTypes.FILE_TYPE],DIR_TYPES=new Set([EntryTypes.DIR_TYPE,EntryTypes.EVERYTHING_TYPE,EntryTypes.FILE_DIR_TYPE]),FILE_TYPES=new Set([EntryTypes.EVERYTHING_TYPE,EntryTypes.FILE_DIR_TYPE,EntryTypes.FILE_TYPE]),wantBigintFsStats=process.platform==="win32";ReaddirpStream=class ReaddirpStream extends Readable{parents;reading;parent;_stat;_maxDepth;_wantsDir;_wantsFile;_wantsEverything;_root;_isDirent;_statsProp;_rdOptions;_fileFilter;_directoryFilter;constructor(options={}){super({objectMode:!0,autoDestroy:!0,highWaterMark:options.highWaterMark});let opts={...defaultOptions,...options},{root,type:type2}=opts;this._fileFilter=normalizeFilter(opts.fileFilter),this._directoryFilter=normalizeFilter(opts.directoryFilter);let statMethod=opts.lstat?lstat:stat5;if(wantBigintFsStats)this._stat=(path3)=>statMethod(path3,{bigint:!0});else this._stat=statMethod;this._maxDepth=opts.depth!=null&&Number.isSafeInteger(opts.depth)?opts.depth:defaultOptions.depth,this._wantsDir=type2?DIR_TYPES.has(type2):!1,this._wantsFile=type2?FILE_TYPES.has(type2):!1,this._wantsEverything=type2===EntryTypes.EVERYTHING_TYPE,this._root=presolve(root),this._isDirent=!opts.alwaysStat,this._statsProp=this._isDirent?"dirent":"stats",this._rdOptions={encoding:"utf8",withFileTypes:this._isDirent},this.parents=[this._exploreDir(root,1)],this.reading=!1,this.parent=void 0}async _read(batch){if(this.reading)return;this.reading=!0;try{while(!this.destroyed&&batch>0){let par=this.parent,fil=par&&par.files;if(fil&&fil.length>0){let{path:path3,depth}=par,slice=fil.splice(0,batch).map((dirent)=>this._formatEntry(dirent,path3)),awaited=await Promise.all(slice);for(let entry2 of awaited){if(!entry2)continue;if(this.destroyed)return;let entryType=await this._getEntryType(entry2);if(entryType==="directory"&&this._directoryFilter(entry2)){if(depth<=this._maxDepth)this.parents.push(this._exploreDir(entry2.fullPath,depth+1));if(this._wantsDir)this.push(entry2),batch--}else if((entryType==="file"||this._includeAsFile(entry2))&&this._fileFilter(entry2)){if(this._wantsFile)this.push(entry2),batch--}}}else{let parent=this.parents.pop();if(!parent){this.push(null);break}if(this.parent=await parent,this.destroyed)return}}}catch(error2){this.destroy(error2)}finally{this.reading=!1}}async _exploreDir(path3,depth){let files;try{files=await readdir7(path3,this._rdOptions)}catch(error2){this._onError(error2)}return{files,depth,path:path3}}async _formatEntry(dirent,path3){let entry2,basename6=this._isDirent?dirent.name:dirent;try{let fullPath=presolve(pjoin(path3,basename6));entry2={path:prelative(this._root,fullPath),fullPath,basename:basename6},entry2[this._statsProp]=this._isDirent?dirent:await this._stat(fullPath)}catch(err){this._onError(err);return}return entry2}_onError(err){if(isNormalFlowError(err)&&!this.destroyed)this.emit("warn",err);else this.destroy(err)}async _getEntryType(entry2){if(!entry2&&this._statsProp in entry2)return"";let stats2=entry2[this._statsProp];if(stats2.isFile())return"file";if(stats2.isDirectory())return"directory";if(stats2&&stats2.isSymbolicLink()){let full=entry2.fullPath;try{let entryRealPath=await realpath(full),entryRealPathStats=await lstat(entryRealPath);if(entryRealPathStats.isFile())return"file";if(entryRealPathStats.isDirectory()){let len=entryRealPath.length;if(full.startsWith(entryRealPath)&&full.substr(len,1)===psep){let recursiveError=Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);return recursiveError.code=RECURSIVE_ERROR_CODE,this._onError(recursiveError)}return"directory"}}catch(error2){return this._onError(error2),""}}}_includeAsFile(entry2){let stats2=entry2&&entry2[this._statsProp];return stats2&&this._wantsEverything&&!stats2.isDirectory()}}});import{watch as fs_watch,unwatchFile,watchFile}from"fs";import{realpath as fsrealpath,lstat as lstat2,open as open4,stat as stat6}from"fs/promises";import{type as osType}from"os";import*as sp from"path";function createFsWatchInstance(path3,options,listener,errHandler,emitRaw){let handleEvent=(rawEvent,evPath)=>{if(listener(path3),emitRaw(rawEvent,evPath,{watchedPath:path3}),evPath&&path3!==evPath)fsWatchBroadcast(sp.resolve(path3,evPath),KEY_LISTENERS,sp.join(path3,evPath))};try{return fs_watch(path3,{persistent:options.persistent},handleEvent)}catch(error2){errHandler(error2);return}}class NodeFsHandler{fsw;_boundHandleError;constructor(fsW){this.fsw=fsW,this._boundHandleError=(error2)=>fsW._handleError(error2)}_watchWithNodeFs(path3,listener){let opts=this.fsw.options,directory=sp.dirname(path3),basename7=sp.basename(path3);this.fsw._getWatchedDir(directory).add(basename7);let absolutePath=sp.resolve(path3),options={persistent:opts.persistent};if(!listener)listener=EMPTY_FN;let closer;if(opts.usePolling){let enableBin=opts.interval!==opts.binaryInterval;options.interval=enableBin&&isBinaryPath(basename7)?opts.binaryInterval:opts.interval,closer=setFsWatchFileListener(path3,absolutePath,options,{listener,rawEmitter:this.fsw._emitRaw})}else closer=setFsWatchListener(path3,absolutePath,options,{listener,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return closer}_handleFile(file,stats2,initialAdd){if(this.fsw.closed)return;let dirname19=sp.dirname(file),basename7=sp.basename(file),parent=this.fsw._getWatchedDir(dirname19),prevStats=stats2;if(parent.has(basename7))return;let listener=async(path3,newStats)=>{if(!this.fsw._throttle(THROTTLE_MODE_WATCH,file,5))return;if(!newStats||newStats.mtimeMs===0)try{let newStats2=await stat6(file);if(this.fsw.closed)return;let{atimeMs:at,mtimeMs:mt}=newStats2;if(!at||at<=mt||mt!==prevStats.mtimeMs)this.fsw._emit(EV.CHANGE,file,newStats2);if((isMacos||isLinux||isFreeBSD)&&prevStats.ino!==newStats2.ino){this.fsw._closeFile(path3),prevStats=newStats2;let closer2=this._watchWithNodeFs(file,listener);if(closer2)this.fsw._addPathCloser(path3,closer2)}else prevStats=newStats2}catch(error2){this.fsw._remove(dirname19,basename7)}else if(parent.has(basename7)){let{atimeMs:at,mtimeMs:mt}=newStats;if(!at||at<=mt||mt!==prevStats.mtimeMs)this.fsw._emit(EV.CHANGE,file,newStats);prevStats=newStats}},closer=this._watchWithNodeFs(file,listener);if(!(initialAdd&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(file)){if(!this.fsw._throttle(EV.ADD,file,0))return;this.fsw._emit(EV.ADD,file,stats2)}return closer}async _handleSymlink(entry2,directory,path3,item){if(this.fsw.closed)return;let full=entry2.fullPath,dir=this.fsw._getWatchedDir(directory);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let linkPath;try{linkPath=await fsrealpath(path3)}catch(e){return this.fsw._emitReady(),!0}if(this.fsw.closed)return;if(dir.has(item)){if(this.fsw._symlinkPaths.get(full)!==linkPath)this.fsw._symlinkPaths.set(full,linkPath),this.fsw._emit(EV.CHANGE,path3,entry2.stats)}else dir.add(item),this.fsw._symlinkPaths.set(full,linkPath),this.fsw._emit(EV.ADD,path3,entry2.stats);return this.fsw._emitReady(),!0}if(this.fsw._symlinkPaths.has(full))return!0;this.fsw._symlinkPaths.set(full,!0)}_handleRead(directory,initialAdd,wh,target,dir,depth,throttler){directory=sp.join(directory,"");let throttleKey=target?`${directory}:${target}`:directory;if(throttler=this.fsw._throttle("readdir",throttleKey,1000),!throttler)return;let previous=this.fsw._getWatchedDir(wh.path),current=new Set,stream=this.fsw._readdirp(directory,{fileFilter:(entry2)=>wh.filterPath(entry2),directoryFilter:(entry2)=>wh.filterDir(entry2)});if(!stream)return;return stream.on(STR_DATA,async(entry2)=>{if(this.fsw.closed){stream=void 0;return}let item=entry2.path,path3=sp.join(directory,item);if(current.add(item),entry2.stats.isSymbolicLink()&&await this._handleSymlink(entry2,directory,path3,item))return;if(this.fsw.closed){stream=void 0;return}if(item===target||!target&&!previous.has(item))this.fsw._incrReadyCount(),path3=sp.join(dir,sp.relative(dir,path3)),this._addToNodeFs(path3,initialAdd,wh,depth+1)}).on(EV.ERROR,this._boundHandleError),new Promise((resolve10,reject)=>{if(!stream)return reject();stream.once(STR_END,()=>{if(this.fsw.closed){stream=void 0;return}let wasThrottled=throttler?throttler.clear():!1;if(resolve10(void 0),previous.getChildren().filter((item)=>{return item!==directory&&!current.has(item)}).forEach((item)=>{this.fsw._remove(directory,item)}),stream=void 0,wasThrottled)this._handleRead(directory,!1,wh,target,dir,depth,throttler)})})}async _handleDir(dir,stats2,initialAdd,depth,target,wh,realpath2){let parentDir=this.fsw._getWatchedDir(sp.dirname(dir)),tracked=parentDir.has(sp.basename(dir));if(!(initialAdd&&this.fsw.options.ignoreInitial)&&!target&&!tracked)this.fsw._emit(EV.ADD_DIR,dir,stats2);parentDir.add(sp.basename(dir)),this.fsw._getWatchedDir(dir);let throttler,closer,oDepth=this.fsw.options.depth;if((oDepth==null||depth<=oDepth)&&!this.fsw._symlinkPaths.has(realpath2)){if(!target){if(await this._handleRead(dir,initialAdd,wh,target,dir,depth,throttler),this.fsw.closed)return}closer=this._watchWithNodeFs(dir,(dirPath,stats3)=>{if(stats3&&stats3.mtimeMs===0)return;this._handleRead(dirPath,!1,wh,target,dir,depth,throttler)})}return closer}async _addToNodeFs(path3,initialAdd,priorWh,depth,target){let ready=this.fsw._emitReady;if(this.fsw._isIgnored(path3)||this.fsw.closed)return ready(),!1;let wh=this.fsw._getWatchHelpers(path3);if(priorWh)wh.filterPath=(entry2)=>priorWh.filterPath(entry2),wh.filterDir=(entry2)=>priorWh.filterDir(entry2);try{let stats2=await statMethods[wh.statMethod](wh.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(wh.watchPath,stats2))return ready(),!1;let follow=this.fsw.options.followSymlinks,closer;if(stats2.isDirectory()){let absPath=sp.resolve(path3),targetPath=follow?await fsrealpath(path3):path3;if(this.fsw.closed)return;if(closer=await this._handleDir(wh.watchPath,stats2,initialAdd,depth,target,wh,targetPath),this.fsw.closed)return;if(absPath!==targetPath&&targetPath!==void 0)this.fsw._symlinkPaths.set(absPath,targetPath)}else if(stats2.isSymbolicLink()){let targetPath=follow?await fsrealpath(path3):path3;if(this.fsw.closed)return;let parent=sp.dirname(wh.watchPath);if(this.fsw._getWatchedDir(parent).add(wh.watchPath),this.fsw._emit(EV.ADD,wh.watchPath,stats2),closer=await this._handleDir(parent,stats2,initialAdd,depth,path3,wh,targetPath),this.fsw.closed)return;if(targetPath!==void 0)this.fsw._symlinkPaths.set(sp.resolve(path3),targetPath)}else closer=this._handleFile(wh.watchPath,stats2,initialAdd);if(ready(),closer)this.fsw._addPathCloser(path3,closer);return!1}catch(error2){if(this.fsw._handleError(error2))return ready(),path3}}}var STR_DATA="data",STR_END="end",STR_CLOSE="close",EMPTY_FN=()=>{},pl,isWindows,isMacos,isLinux,isFreeBSD,isIBMi,EVENTS,EV,THROTTLE_MODE_WATCH="watch",statMethods,KEY_LISTENERS="listeners",KEY_ERR="errHandlers",KEY_RAW="rawEmitters",HANDLER_KEYS,binaryExtensions,isBinaryPath=(filePath)=>binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase()),foreach=(val,fn)=>{if(val instanceof Set)val.forEach(fn);else fn(val)},addAndConvert=(main,prop,item)=>{let container=main[prop];if(!(container instanceof Set))main[prop]=container=new Set([container]);container.add(item)},clearItem=(cont)=>(key)=>{let set2=cont[key];if(set2 instanceof Set)set2.clear();else delete cont[key]},delFromSet=(main,prop,item)=>{let container=main[prop];if(container instanceof Set)container.delete(item);else if(container===item)delete main[prop]},isEmptySet=(val)=>val instanceof Set?val.size===0:!val,FsWatchInstances,fsWatchBroadcast=(fullPath,listenerType,val1,val2,val3)=>{let cont=FsWatchInstances.get(fullPath);if(!cont)return;foreach(cont[listenerType],(listener)=>{listener(val1,val2,val3)})},setFsWatchListener=(path3,fullPath,options,handlers)=>{let{listener,errHandler,rawEmitter}=handlers,cont=FsWatchInstances.get(fullPath),watcher;if(!options.persistent){if(watcher=createFsWatchInstance(path3,options,listener,errHandler,rawEmitter),!watcher)return;return watcher.close.bind(watcher)}if(cont)addAndConvert(cont,KEY_LISTENERS,listener),addAndConvert(cont,KEY_ERR,errHandler),addAndConvert(cont,KEY_RAW,rawEmitter);else{if(watcher=createFsWatchInstance(path3,options,fsWatchBroadcast.bind(null,fullPath,KEY_LISTENERS),errHandler,fsWatchBroadcast.bind(null,fullPath,KEY_RAW)),!watcher)return;watcher.on(EV.ERROR,async(error2)=>{let broadcastErr=fsWatchBroadcast.bind(null,fullPath,KEY_ERR);if(cont)cont.watcherUnusable=!0;if(isWindows&&error2.code==="EPERM")try{await(await open4(path3,"r")).close(),broadcastErr(error2)}catch(err){}else broadcastErr(error2)}),cont={listeners:listener,errHandlers:errHandler,rawEmitters:rawEmitter,watcher},FsWatchInstances.set(fullPath,cont)}return()=>{if(delFromSet(cont,KEY_LISTENERS,listener),delFromSet(cont,KEY_ERR,errHandler),delFromSet(cont,KEY_RAW,rawEmitter),isEmptySet(cont.listeners))cont.watcher.close(),FsWatchInstances.delete(fullPath),HANDLER_KEYS.forEach(clearItem(cont)),cont.watcher=void 0,Object.freeze(cont)}},FsWatchFileInstances,setFsWatchFileListener=(path3,fullPath,options,handlers)=>{let{listener,rawEmitter}=handlers,cont=FsWatchFileInstances.get(fullPath),copts=cont&&cont.options;if(copts&&(copts.persistent<options.persistent||copts.interval>options.interval))unwatchFile(fullPath),cont=void 0;if(cont)addAndConvert(cont,KEY_LISTENERS,listener),addAndConvert(cont,KEY_RAW,rawEmitter);else cont={listeners:listener,rawEmitters:rawEmitter,options,watcher:watchFile(fullPath,options,(curr,prev)=>{foreach(cont.rawEmitters,(rawEmitter2)=>{rawEmitter2(EV.CHANGE,fullPath,{curr,prev})});let currmtime=curr.mtimeMs;if(curr.size!==prev.size||currmtime>prev.mtimeMs||currmtime===0)foreach(cont.listeners,(listener2)=>listener2(path3,curr))})},FsWatchFileInstances.set(fullPath,cont);return()=>{if(delFromSet(cont,KEY_LISTENERS,listener),delFromSet(cont,KEY_RAW,rawEmitter),isEmptySet(cont.listeners))FsWatchFileInstances.delete(fullPath),unwatchFile(fullPath),cont.options=cont.watcher=void 0,Object.freeze(cont)}};var init_handler=__esm(()=>{pl=process.platform,isWindows=pl==="win32",isMacos=pl==="darwin",isLinux=pl==="linux",isFreeBSD=pl==="freebsd",isIBMi=osType()==="OS400",EVENTS={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},EV=EVENTS,statMethods={lstat:lstat2,stat:stat6},HANDLER_KEYS=[KEY_LISTENERS,KEY_ERR,KEY_RAW],binaryExtensions=new Set(["3dm","3ds","3g2","3gp","7z","a","aac","adp","afdesign","afphoto","afpub","ai","aif","aiff","alz","ape","apk","appimage","ar","arj","asf","au","avi","bak","baml","bh","bin","bk","bmp","btif","bz2","bzip2","cab","caf","cgm","class","cmx","cpio","cr2","cur","dat","dcm","deb","dex","djvu","dll","dmg","dng","doc","docm","docx","dot","dotm","dra","DS_Store","dsk","dts","dtshd","dvb","dwg","dxf","ecelp4800","ecelp7470","ecelp9600","egg","eol","eot","epub","exe","f4v","fbs","fh","fla","flac","flatpak","fli","flv","fpx","fst","fvt","g3","gh","gif","graffle","gz","gzip","h261","h263","h264","icns","ico","ief","img","ipa","iso","jar","jpeg","jpg","jpgv","jpm","jxr","key","ktx","lha","lib","lvp","lz","lzh","lzma","lzo","m3u","m4a","m4v","mar","mdi","mht","mid","midi","mj2","mka","mkv","mmr","mng","mobi","mov","movie","mp3","mp4","mp4a","mpeg","mpg","mpga","mxu","nef","npx","numbers","nupkg","o","odp","ods","odt","oga","ogg","ogv","otf","ott","pages","pbm","pcx","pdb","pdf","pea","pgm","pic","png","pnm","pot","potm","potx","ppa","ppam","ppm","pps","ppsm","ppsx","ppt","pptm","pptx","psd","pya","pyc","pyo","pyv","qt","rar","ras","raw","resources","rgb","rip","rlc","rmf","rmvb","rpm","rtf","rz","s3m","s7z","scpt","sgi","shar","snap","sil","sketch","slk","smv","snk","so","stl","suo","sub","swf","tar","tbz","tbz2","tga","tgz","thmx","tif","tiff","tlz","ttc","ttf","txz","udf","uvh","uvi","uvm","uvp","uvs","uvu","viv","vob","war","wav","wax","wbmp","wdp","weba","webm","webp","whl","wim","wm","wma","wmv","wmx","woff","woff2","wrm","wvx","xbm","xif","xla","xlam","xls","xlsb","xlsm","xlsx","xlt","xltm","xltx","xm","xmind","xpi","xpm","xwd","xz","z","zip","zipx"]),FsWatchInstances=new Map;FsWatchFileInstances=new Map});import{EventEmitter}from"events";import{stat as statcb,Stats}from"fs";import{readdir as readdir8,stat as stat7}from"fs/promises";import*as sp2 from"path";function arrify(item){return Array.isArray(item)?item:[item]}function createPattern(matcher){if(typeof matcher==="function")return matcher;if(typeof matcher==="string")return(string)=>matcher===string;if(matcher instanceof RegExp)return(string)=>matcher.test(string);if(typeof matcher==="object"&&matcher!==null)return(string)=>{if(matcher.path===string)return!0;if(matcher.recursive){let relative4=sp2.relative(matcher.path,string);if(!relative4)return!1;return!relative4.startsWith("..")&&!sp2.isAbsolute(relative4)}return!1};return()=>!1}function normalizePath(path3){if(typeof path3!=="string")throw Error("string expected");path3=sp2.normalize(path3),path3=path3.replace(/\\/g,"/");let prepend=!1;if(path3.startsWith("//"))prepend=!0;if(path3=path3.replace(DOUBLE_SLASH_RE,"/"),prepend)path3="/"+path3;return path3}function matchPatterns2(patterns2,testString,stats2){let path3=normalizePath(testString);for(let index=0;index<patterns2.length;index++){let pattern=patterns2[index];if(pattern(path3,stats2))return!0}return!1}function anymatch(matchers,testString){if(matchers==null)throw TypeError("anymatch: specify first argument");let patterns2=arrify(matchers).map((matcher)=>createPattern(matcher));if(testString==null)return(testString2,stats2)=>{return matchPatterns2(patterns2,testString2,stats2)};return matchPatterns2(patterns2,testString)}class DirEntry{path;_removeWatcher;items;constructor(dir,removeWatcher){this.path=dir,this._removeWatcher=removeWatcher,this.items=new Set}add(item){let{items}=this;if(!items)return;if(item!==ONE_DOT&&item!==TWO_DOTS)items.add(item)}async remove(item){let{items}=this;if(!items)return;if(items.delete(item),items.size>0)return;let dir=this.path;try{await readdir8(dir)}catch(err){if(this._removeWatcher)this._removeWatcher(sp2.dirname(dir),sp2.basename(dir))}}has(item){let{items}=this;if(!items)return;return items.has(item)}getChildren(){let{items}=this;if(!items)return[];return[...items.values()]}dispose(){this.items.clear(),this.path="",this._removeWatcher=EMPTY_FN,this.items=EMPTY_SET,Object.freeze(this)}}class WatchHelper{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(path3,follow,fsw){this.fsw=fsw;let watchPath=path3;this.path=path3=path3.replace(REPLACER_RE,""),this.watchPath=watchPath,this.fullWatchPath=sp2.resolve(watchPath),this.dirParts=[],this.dirParts.forEach((parts)=>{if(parts.length>1)parts.pop()}),this.followSymlinks=follow,this.statMethod=follow?STAT_METHOD_F:STAT_METHOD_L}entryPath(entry2){return sp2.join(this.watchPath,sp2.relative(this.watchPath,entry2.fullPath))}filterPath(entry2){let{stats:stats2}=entry2;if(stats2&&stats2.isSymbolicLink())return this.filterDir(entry2);let resolvedPath=this.entryPath(entry2);return this.fsw._isntIgnored(resolvedPath,stats2)&&this.fsw._hasReadPermissions(stats2)}filterDir(entry2){return this.fsw._isntIgnored(this.entryPath(entry2),entry2.stats)}}function watch(paths,options={}){let watcher=new FSWatcher(options);return watcher.add(paths),watcher}var SLASH="/",SLASH_SLASH="//",ONE_DOT=".",TWO_DOTS="..",STRING_TYPE="string",BACK_SLASH_RE,DOUBLE_SLASH_RE,DOT_RE,REPLACER_RE,isMatcherObject=(matcher)=>typeof matcher==="object"&&matcher!==null&&!(matcher instanceof RegExp),unifyPaths=(paths_)=>{let paths=arrify(paths_).flat();if(!paths.every((p)=>typeof p===STRING_TYPE))throw TypeError(`Non-string provided as watch path: ${paths}`);return paths.map(normalizePathToUnix)},toUnix=(string)=>{let str3=string.replace(BACK_SLASH_RE,SLASH),prepend=!1;if(str3.startsWith(SLASH_SLASH))prepend=!0;if(str3=str3.replace(DOUBLE_SLASH_RE,SLASH),prepend)str3=SLASH+str3;return str3},normalizePathToUnix=(path3)=>toUnix(sp2.normalize(toUnix(path3))),normalizeIgnored=(cwd="")=>(path3)=>{if(typeof path3==="string")return normalizePathToUnix(sp2.isAbsolute(path3)?path3:sp2.join(cwd,path3));else return path3},getAbsolutePath=(path3,cwd)=>{if(sp2.isAbsolute(path3))return path3;return sp2.join(cwd,path3)},EMPTY_SET,STAT_METHOD_F="stat",STAT_METHOD_L="lstat",FSWatcher;var init_chokidar=__esm(()=>{init_readdirp();init_handler();/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */BACK_SLASH_RE=/\\/g,DOUBLE_SLASH_RE=/\/\//g,DOT_RE=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,REPLACER_RE=/^\.[/\\]/;EMPTY_SET=Object.freeze(new Set);FSWatcher=class FSWatcher extends EventEmitter{closed;options;_closers;_ignoredPaths;_throttled;_streams;_symlinkPaths;_watched;_pendingWrites;_pendingUnlinks;_readyCount;_emitReady;_closePromise;_userIgnored;_readyEmitted;_emitRaw;_boundRemove;_nodeFsHandler;constructor(_opts={}){super();this.closed=!1,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._streams=new Set,this._symlinkPaths=new Map,this._watched=new Map,this._pendingWrites=new Map,this._pendingUnlinks=new Map,this._readyCount=0,this._readyEmitted=!1;let awf=_opts.awaitWriteFinish,DEF_AWF={stabilityThreshold:2000,pollInterval:100},opts={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,..._opts,ignored:_opts.ignored?arrify(_opts.ignored):arrify([]),awaitWriteFinish:awf===!0?DEF_AWF:typeof awf==="object"?{...DEF_AWF,...awf}:!1};if(isIBMi)opts.usePolling=!0;if(opts.atomic===void 0)opts.atomic=!opts.usePolling;let envPoll=process.env.CHOKIDAR_USEPOLLING;if(envPoll!==void 0){let envLower=envPoll.toLowerCase();if(envLower==="false"||envLower==="0")opts.usePolling=!1;else if(envLower==="true"||envLower==="1")opts.usePolling=!0;else opts.usePolling=!!envLower}let envInterval=process.env.CHOKIDAR_INTERVAL;if(envInterval)opts.interval=Number.parseInt(envInterval,10);let readyCalls=0;this._emitReady=()=>{if(readyCalls++,readyCalls>=this._readyCount)this._emitReady=EMPTY_FN,this._readyEmitted=!0,process.nextTick(()=>this.emit(EVENTS.READY))},this._emitRaw=(...args)=>this.emit(EVENTS.RAW,...args),this._boundRemove=this._remove.bind(this),this.options=opts,this._nodeFsHandler=new NodeFsHandler(this),Object.freeze(opts)}_addIgnoredPath(matcher){if(isMatcherObject(matcher)){for(let ignored of this._ignoredPaths)if(isMatcherObject(ignored)&&ignored.path===matcher.path&&ignored.recursive===matcher.recursive)return}this._ignoredPaths.add(matcher)}_removeIgnoredPath(matcher){if(this._ignoredPaths.delete(matcher),typeof matcher==="string"){for(let ignored of this._ignoredPaths)if(isMatcherObject(ignored)&&ignored.path===matcher)this._ignoredPaths.delete(ignored)}}add(paths_,_origAdd,_internal){let{cwd}=this.options;this.closed=!1,this._closePromise=void 0;let paths=unifyPaths(paths_);if(cwd)paths=paths.map((path3)=>{return getAbsolutePath(path3,cwd)});if(paths.forEach((path3)=>{this._removeIgnoredPath(path3)}),this._userIgnored=void 0,!this._readyCount)this._readyCount=0;return this._readyCount+=paths.length,Promise.all(paths.map(async(path3)=>{let res=await this._nodeFsHandler._addToNodeFs(path3,!_internal,void 0,0,_origAdd);if(res)this._emitReady();return res})).then((results)=>{if(this.closed)return;results.forEach((item)=>{if(item)this.add(sp2.dirname(item),sp2.basename(_origAdd||item))})}),this}unwatch(paths_){if(this.closed)return this;let paths=unifyPaths(paths_),{cwd}=this.options;return paths.forEach((path3)=>{if(!sp2.isAbsolute(path3)&&!this._closers.has(path3)){if(cwd)path3=sp2.join(cwd,path3);path3=sp2.resolve(path3)}if(this._closePath(path3),this._addIgnoredPath(path3),this._watched.has(path3))this._addIgnoredPath({path:path3,recursive:!0});this._userIgnored=void 0}),this}close(){if(this._closePromise)return this._closePromise;this.closed=!0,this.removeAllListeners();let closers=[];return this._closers.forEach((closerList)=>closerList.forEach((closer)=>{let promise=closer();if(promise instanceof Promise)closers.push(promise)})),this._streams.forEach((stream)=>stream.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=!1,this._watched.forEach((dirent)=>dirent.dispose()),this._closers.clear(),this._watched.clear(),this._streams.clear(),this._symlinkPaths.clear(),this._throttled.clear(),this._closePromise=closers.length?Promise.all(closers).then(()=>{return}):Promise.resolve(),this._closePromise}getWatched(){let watchList={};return this._watched.forEach((entry2,dir)=>{let index=(this.options.cwd?sp2.relative(this.options.cwd,dir):dir)||ONE_DOT;watchList[index]=entry2.getChildren().sort()}),watchList}emitWithAll(event,args){if(this.emit(event,...args),event!==EVENTS.ERROR)this.emit(EVENTS.ALL,event,...args)}async _emit(event,path3,stats2){if(this.closed)return;let opts=this.options;if(isWindows)path3=sp2.normalize(path3);if(opts.cwd)path3=sp2.relative(opts.cwd,path3);let args=[path3];if(stats2!=null)args.push(stats2);let awf=opts.awaitWriteFinish,pw;if(awf&&(pw=this._pendingWrites.get(path3)))return pw.lastChange=new Date,this;if(opts.atomic){if(event===EVENTS.UNLINK)return this._pendingUnlinks.set(path3,[event,...args]),setTimeout(()=>{this._pendingUnlinks.forEach((entry2,path4)=>{this.emit(...entry2),this.emit(EVENTS.ALL,...entry2),this._pendingUnlinks.delete(path4)})},typeof opts.atomic==="number"?opts.atomic:100),this;if(event===EVENTS.ADD&&this._pendingUnlinks.has(path3))event=EVENTS.CHANGE,this._pendingUnlinks.delete(path3)}if(awf&&(event===EVENTS.ADD||event===EVENTS.CHANGE)&&this._readyEmitted){let awfEmit=(err,stats3)=>{if(err)event=EVENTS.ERROR,args[0]=err,this.emitWithAll(event,args);else if(stats3){if(args.length>1)args[1]=stats3;else args.push(stats3);this.emitWithAll(event,args)}};return this._awaitWriteFinish(path3,awf.stabilityThreshold,event,awfEmit),this}if(event===EVENTS.CHANGE){if(!this._throttle(EVENTS.CHANGE,path3,50))return this}if(opts.alwaysStat&&stats2===void 0&&(event===EVENTS.ADD||event===EVENTS.ADD_DIR||event===EVENTS.CHANGE)){let fullPath=opts.cwd?sp2.join(opts.cwd,path3):path3,stats3;try{stats3=await stat7(fullPath)}catch(err){}if(!stats3||this.closed)return;args.push(stats3)}return this.emitWithAll(event,args),this}_handleError(error2){let code=error2&&error2.code;if(error2&&code!=="ENOENT"&&code!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||code!=="EPERM"&&code!=="EACCES"))this.emit(EVENTS.ERROR,error2);return error2||this.closed}_throttle(actionType,path3,timeout){if(!this._throttled.has(actionType))this._throttled.set(actionType,new Map);let action=this._throttled.get(actionType);if(!action)throw Error("invalid throttle");let actionPath=action.get(path3);if(actionPath)return actionPath.count++,!1;let timeoutObject,clear=()=>{let item=action.get(path3),count=item?item.count:0;if(action.delete(path3),clearTimeout(timeoutObject),item)clearTimeout(item.timeoutObject);return count};timeoutObject=setTimeout(clear,timeout);let thr={timeoutObject,clear,count:0};return action.set(path3,thr),thr}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(path3,threshold,event,awfEmit){let awf=this.options.awaitWriteFinish;if(typeof awf!=="object")return;let pollInterval=awf.pollInterval,timeoutHandler,fullPath=path3;if(this.options.cwd&&!sp2.isAbsolute(path3))fullPath=sp2.join(this.options.cwd,path3);let now=new Date,writes=this._pendingWrites;function awaitWriteFinishFn(prevStat){statcb(fullPath,(err,curStat)=>{if(err||!writes.has(path3)){if(err&&err.code!=="ENOENT")awfEmit(err);return}let now2=Number(new Date);if(prevStat&&curStat.size!==prevStat.size)writes.get(path3).lastChange=now2;let pw=writes.get(path3);if(now2-pw.lastChange>=threshold)writes.delete(path3),awfEmit(void 0,curStat);else timeoutHandler=setTimeout(awaitWriteFinishFn,pollInterval,curStat)})}if(!writes.has(path3))writes.set(path3,{lastChange:now,cancelWait:()=>{return writes.delete(path3),clearTimeout(timeoutHandler),event}}),timeoutHandler=setTimeout(awaitWriteFinishFn,pollInterval)}_isIgnored(path3,stats2){if(this.options.atomic&&DOT_RE.test(path3))return!0;if(!this._userIgnored){let{cwd}=this.options,ignored=(this.options.ignored||[]).map(normalizeIgnored(cwd)),list2=[...[...this._ignoredPaths].map(normalizeIgnored(cwd)),...ignored];this._userIgnored=anymatch(list2,void 0)}return this._userIgnored(path3,stats2)}_isntIgnored(path3,stat8){return!this._isIgnored(path3,stat8)}_getWatchHelpers(path3){return new WatchHelper(path3,this.options.followSymlinks,this)}_getWatchedDir(directory){let dir=sp2.resolve(directory);if(!this._watched.has(dir))this._watched.set(dir,new DirEntry(dir,this._boundRemove));return this._watched.get(dir)}_hasReadPermissions(stats2){if(this.options.ignorePermissionErrors)return!0;return Boolean(Number(stats2.mode)&256)}_remove(directory,item,isDirectory){let path3=sp2.join(directory,item),fullPath=sp2.resolve(path3);if(isDirectory=isDirectory!=null?isDirectory:this._watched.has(path3)||this._watched.has(fullPath),!this._throttle("remove",path3,100))return;if(!isDirectory&&this._watched.size===1)this.add(directory,item,!0);this._getWatchedDir(path3).getChildren().forEach((nested)=>this._remove(path3,nested));let parent=this._getWatchedDir(directory),wasTracked=parent.has(item);if(parent.remove(item),this._symlinkPaths.has(fullPath))this._symlinkPaths.delete(fullPath);let relPath=path3;if(this.options.cwd)relPath=sp2.relative(this.options.cwd,path3);if(this.options.awaitWriteFinish&&this._pendingWrites.has(relPath)){if(this._pendingWrites.get(relPath).cancelWait()===EVENTS.ADD)return}this._watched.delete(path3),this._watched.delete(fullPath);let eventName=isDirectory?EVENTS.UNLINK_DIR:EVENTS.UNLINK;if(wasTracked&&!this._isIgnored(path3))this._emit(eventName,path3);this._closePath(path3)}_closePath(path3){this._closeFile(path3);let dir=sp2.dirname(path3);this._getWatchedDir(dir).remove(sp2.basename(path3))}_closeFile(path3){let closers=this._closers.get(path3);if(!closers)return;closers.forEach((closer)=>closer()),this._closers.delete(path3)}_addPathCloser(path3,closer){if(!closer)return;let list2=this._closers.get(path3);if(!list2)list2=[],this._closers.set(path3,list2);list2.push(closer)}_readdirp(root,opts){if(this.closed)return;let options={type:EVENTS.ALL,alwaysStat:!0,lstat:!0,...opts,depth:0},stream=readdirp(root,options);return this._streams.add(stream),stream.once(STR_CLOSE,()=>{stream=void 0}),stream.once(STR_END,()=>{if(stream)this._streams.delete(stream),stream=void 0}),stream}}});var exports_session_filewatch={};__export(exports_session_filewatch,{stopFilewatch:()=>stopFilewatch,startFilewatch:()=>startFilewatch,resetUnrecoverableSessions:()=>resetUnrecoverableSessions,isTransientPgConnectionError:()=>isTransientPgConnectionError,isForeignKeyViolation:()=>isForeignKeyViolation,handleFileChange:()=>handleFileChange,extractSessionInfo:()=>extractSessionInfo,createJsonlWatcher:()=>createJsonlWatcher});import{homedir as homedir37}from"os";import{basename as basename8,isAbsolute as isAbsolute4,join as join58,resolve as resolve11}from"path";function resetUnrecoverableSessions(){unrecoverableSessions.clear(),offsetCache.clear()}function isForeignKeyViolation(err){if(!err||typeof err!=="object")return!1;let code=err.code;if(typeof code==="string"&&code==="23503")return!0;return(err instanceof Error?err.message:String(err)).toLowerCase().includes("foreign key constraint")}function isTransientPgConnectionError(err){if(!err||typeof err!=="object")return!1;let code=err.code;if(typeof code==="string"&&["CONNECTION_ENDED","CONNECTION_DESTROYED","CONNECT_TIMEOUT","ECONNRESET","EPIPE"].includes(code))return!0;let message=err instanceof Error?err.message:String(err);return/CONNECTION_ENDED|CONNECTION_DESTROYED|CONNECT_TIMEOUT|ECONNRESET|EPIPE|connection terminated|connection closed|server closed the connection/i.test(message)}async function loadOffsets(sql){try{let rows=await sql`SELECT id, last_ingested_offset FROM sessions WHERE last_ingested_offset > 0`;for(let row2 of rows)offsetCache.set(row2.id,row2.last_ingested_offset)}catch{}}function extractSessionInfo(filePath){if(!filePath.endsWith(".jsonl"))return null;let sessionId=basename8(filePath,".jsonl"),parts=filePath.split("/"),sessionsIdx=parts.lastIndexOf("sessions"),subagentsIdx=parts.lastIndexOf("subagents");if(subagentsIdx>0&&parts[subagentsIdx-1]){let parentSessionId=parts[subagentsIdx-1],projectIdx2=parts.indexOf("projects"),projectPath=projectIdx2>=0?parts.slice(0,projectIdx2+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}}let projectIdx=parts.lastIndexOf("projects");if(projectIdx>=0&&parts.length===projectIdx+3){let projectPath=parts.slice(0,projectIdx+2).join("/");return{sessionId,projectPath,parentSessionId:null,isSubagent:!1}}return null}async function ingestFileChange(sql,info,filePath,storedOffset,deps){let workerMap=await deps.buildWorkerMap(sql);return(await deps.ingestFileFull(sql,info.sessionId,filePath,info.projectPath,storedOffset,{parentSessionId:info.parentSessionId,isSubagent:info.isSubagent,workerMap})).newOffset}function markSessionUnrecoverable(info,filePath,message,deps){unrecoverableSessions.add(info.sessionId),offsetCache.set(info.sessionId,Number.POSITIVE_INFINITY),deps.logError(`[filewatch] skipping ${filePath} \u2014 FK constraint violation (orphan session, parent not registered): ${message}`)}async function reconnectAfterTransientPgError(err,deps){if(!isTransientPgConnectionError(err)||!deps.getConnection||!deps.resetConnection)return null;try{return await deps.resetConnection(),await deps.getConnection()}catch{return null}}async function tryIngestFileChange(sql,info,filePath,storedOffset,deps){try{return{ok:!0,newOffset:await ingestFileChange(sql,info,filePath,storedOffset,deps)}}catch(err){return{ok:!1,error:err}}}function recordIngestFailure(err,info,filePath,storedOffset,deps){let message=err instanceof Error?err.message:String(err);if(isForeignKeyViolation(err)){markSessionUnrecoverable(info,filePath,message,deps);return}deps.logError(`[filewatch] error ingesting ${filePath} at offset ${storedOffset}: ${message}`)}async function ingestWithOneReconnect(sql,info,filePath,storedOffset,deps){let first=await tryIngestFileChange(sql,info,filePath,storedOffset,deps);if(first.ok){offsetCache.set(info.sessionId,first.newOffset);return}let freshSql=await reconnectAfterTransientPgError(first.error,deps);if(!freshSql){recordIngestFailure(first.error,info,filePath,storedOffset,deps);return}let second=await tryIngestFileChange(freshSql,info,filePath,storedOffset,deps);if(second.ok)offsetCache.set(info.sessionId,second.newOffset);else recordIngestFailure(second.error,info,filePath,storedOffset,deps)}async function handleFileChange(filePath,sql,deps=defaultDeps4){let info=extractSessionInfo(filePath);if(!info)return;if(unrecoverableSessions.has(info.sessionId))return;let storedOffset=offsetCache.get(info.sessionId)??0;try{deps.setLiveWorkPending(!0),await ingestWithOneReconnect(sql,info,filePath,storedOffset,deps)}finally{deps.setLiveWorkPending(!1)}}function shouldIgnoreWatchPath(path3,stats2){return stats2?.isFile()===!0&&!path3.endsWith(".jsonl")}function normalizeWatchEventPath(claudeDir,filePath){return isAbsolute4(filePath)?filePath:resolve11(claudeDir,filePath)}function scheduleFileChange(filePath){if(!filePath.endsWith(".jsonl"))return;let existing=debounceTimers.get(filePath);if(existing)clearTimeout(existing);debounceTimers.set(filePath,setTimeout(()=>{debounceTimers.delete(filePath),getConnection().then((freshSql)=>handleFileChange(filePath,freshSql)).catch((err)=>{let message=err instanceof Error?err.message:String(err);console.error(`[filewatch] unhandled error for ${filePath}: ${message}`)})},DEBOUNCE_MS))}function createJsonlWatcher(claudeDir,onJsonlChange){let jsonlWatcher=watch(claudeDir,{ignoreInitial:!0,depth:WATCH_DEPTH,ignored:shouldIgnoreWatchPath,awaitWriteFinish:{stabilityThreshold:DEBOUNCE_MS,pollInterval:100},atomic:!0}),emitJsonlChange=(filePath)=>{if(!filePath.endsWith(".jsonl"))return;onJsonlChange(normalizeWatchEventPath(claudeDir,filePath))};return jsonlWatcher.on("add",emitJsonlChange),jsonlWatcher.on("change",emitJsonlChange),jsonlWatcher}async function startFilewatch(sql){if(watcher)return!0;let claudeDir=join58(process.env.CLAUDE_CONFIG_DIR??join58(homedir37(),".claude"),"projects");await loadOffsets(sql);try{return watcher=createJsonlWatcher(claudeDir,(fullPath)=>scheduleFileChange(fullPath)),watcher.on("error",(err)=>{let message=err instanceof Error?err.message:String(err);console.error("[filewatch] watcher error:",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,WATCH_DEPTH=4,unrecoverableSessions,defaultDeps4;var init_session_filewatch=__esm(()=>{init_chokidar();init_db();init_session_capture();offsetCache=new Map,debounceTimers=new Map,unrecoverableSessions=new Set;defaultDeps4={buildWorkerMap,ingestFileFull,setLiveWorkPending,logError:(msg)=>console.error(msg),getConnection,resetConnection}});var exports_scheduler_daemon={};__export(exports_scheduler_daemon,{terminalizeCleanExitUnverified:()=>terminalizeCleanExitUnverified,startDaemon:()=>startDaemon,runBootPass:()=>runBootPass,runAgentRecoveryPass:()=>runAgentRecoveryPass,recoverOnStartup:()=>recoverOnStartup,reconcileUnresumable:()=>reconcileUnresumable,reconcileOrphans:()=>reconcileOrphans,reconcileOrphanedRuns:()=>reconcileOrphanedRuns,reclaimExpiredLeases:()=>reclaimExpiredLeases,processMailboxRetryMessage:()=>processMailboxRetryMessage,logToFile:()=>logToFile,logReconcilerMode:()=>logReconcilerMode,isTurnAwareReconcilerEnabled:()=>isTurnAwareReconcilerEnabled,fireTrigger:()=>fireTrigger,emitWorkerEvents:()=>emitWorkerEvents,collectMachineSnapshot:()=>collectMachineSnapshot,collectHeartbeats:()=>collectHeartbeats,claimDueTriggers:()=>claimDueTriggers,attemptAgentResume:()=>attemptAgentResume,_resetWorkerStatesForTesting:()=>_resetWorkerStatesForTesting,TURN_AWARE_RECONCILER_FLAG:()=>TURN_AWARE_RECONCILER_FLAG,MAX_DELIVERY_ATTEMPTS:()=>MAX_DELIVERY_ATTEMPTS,ESCALATION_RECIPIENT:()=>ESCALATION_RECIPIENT});import{randomUUID as randomUUID8}from"crypto";import{appendFileSync as appendFileSync4,mkdirSync as mkdirSync20}from"fs";import{homedir as homedir38}from"os";import{join as join59}from"path";function isTurnAwareReconcilerEnabled(env=process.env){let raw=env[TURN_AWARE_RECONCILER_FLAG];if(raw===void 0)return!0;let v=raw.trim().toLowerCase();if(v==="")return!0;if(v==="0"||v==="false"||v==="no")return!1;if(v==="1"||v==="true"||v==="yes")return!0;return!0}function logReconcilerMode(deps,daemonId){let enabled=isTurnAwareReconcilerEnabled();deps.log({timestamp:deps.now().toISOString(),level:"info",event:enabled?"reconciler_mode_turn_aware":"reconciler_mode_legacy",daemon_id:daemonId,flag:TURN_AWARE_RECONCILER_FLAG,enabled,message:enabled?"turn-aware reconciler enabled":"flag off, using legacy reconciler"})}function getLogDir2(){return join59(process.env.GENIE_HOME??join59(homedir38(),".genie"),"logs")}function getLogFile(){return join59(getLogDir2(),"scheduler.log")}function logToFile(entry2){let logDir=getLogDir2();mkdirSync20(logDir,{recursive:!0});let enriched=entry2.trace_id?entry2:withAmbientTraceId(entry2);appendFileSync4(getLogFile(),`${JSON.stringify(enriched)}
2255
2255
  `)}function withAmbientTraceId(entry2){let ctx=getAmbient();if(!ctx)return entry2;return{...entry2,trace_id:ctx.trace_id}}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((resolve12)=>setTimeout(resolve12,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)),{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),agents=await list2(),sessionByAgent=new Map;try{let rows=await(await getConnection2())`
2256
2256
  SELECT a.id AS agent_id, e.claude_session_id
2257
2257
  FROM agents a
@@ -2630,10 +2630,10 @@ ${queryContent}`;let{messages:queryMessages}=state.provider.runQuery({agentId:se
2630
2630
  UPDATE omni_requests
2631
2631
  SET status = 'pending', started_at = NULL, next_retry_at = ${nextRetry}
2632
2632
  WHERE id = ${id}
2633
- `}}class TurnTracker{turns=new Map;open(sessionKey2,turnId,messageId){this.turns.set(sessionKey2,{turnId,sessionKey:sessionKey2,messageId,startedAt:Date.now(),closed:!1})}close(sessionKey2,action){let turn=this.turns.get(sessionKey2);if(turn&&!turn.closed)turn.closed=!0,turn.closedAction=action}isOpen(sessionKey2){let turn=this.turns.get(sessionKey2);return turn!==void 0&&!turn.closed}getTurnId(sessionKey2){return this.turns.get(sessionKey2)?.turnId}getByTurnId(turnId){for(let turn of this.turns.values())if(turn.turnId===turnId)return turn;return}delete(sessionKey2){this.turns.delete(sessionKey2)}}var exports_omni_bridge={};__export(exports_omni_bridge,{OmniBridge:()=>OmniBridge});import{closeSync as closeSync4,existsSync as existsSync49,mkdirSync as mkdirSync21,openSync as openSync4,readFileSync as readFileSync32,unlinkSync as unlinkSync9,writeSync}from"fs";import{dirname as dirname19}from"path";function withTimeout2(p,ms,label){return new Promise((resolve12,reject)=>{let timer2=setTimeout(()=>reject(Error(`${label} timed out after ${ms}ms`)),ms);timer2.unref?.(),p.then((v)=>{clearTimeout(timer2),resolve12(v)},(err)=>{clearTimeout(timer2),reject(err)})})}function isPgConnectionError(err){if(!err||typeof err!=="object")return!1;let e=err,code=e.code??"";if(["ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENOTFOUND","EPIPE","EHOSTUNREACH"].includes(code))return!0;let msg=e.message??String(err);return/ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EPIPE|connection terminated|connection closed|server closed the connection|the database system is shutting down/i.test(msg)}class OmniBridge{nc=null;sub=null;executor;turnTracker=new TurnTracker;heartbeatPublisher=null;sessions=new Map;messageQueue=[];recentMessageIds=new Map;idleCheckTimer=null;sc=import_nats4.StringCodec();sql=null;pgAvailable=!1;pgProvider;natsConnectFn;queueConfig;queue=null;sessionStore=null;natsUrl;idleTimeoutMs;maxConcurrent;executorType;pidfilePath=null;startedAtMs=0;pingSub=null;signalCleanup=null;constructor(config={}){if(this.natsUrl=config.natsUrl??process.env.GENIE_NATS_URL??DEFAULT_NATS_URL2,this.idleTimeoutMs=config.idleTimeoutMs??(process.env.GENIE_IDLE_TIMEOUT_MS?Number(process.env.GENIE_IDLE_TIMEOUT_MS):DEFAULT_IDLE_TIMEOUT_MS2),this.maxConcurrent=config.maxConcurrent??(process.env.GENIE_MAX_CONCURRENT?Number(process.env.GENIE_MAX_CONCURRENT):DEFAULT_MAX_CONCURRENT),this.pgProvider=config.pgProvider??(async()=>{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return await getConnection2()}),this.natsConnectFn=config.natsConnectFn??import_nats4.connect,this.queueConfig=config.queue??{},this.executorType=resolveExecutorType(config.executorType),this.executorType==="sdk")this.executor=new ClaudeSdkOmniExecutor;else this.executor=new ClaudeCodeOmniExecutor}async start(){if(this.nc){console.log("[omni-bridge] Already running");return}console.log(`[omni-bridge] Connecting to NATS at ${this.natsUrl}...`),this.nc=await this.natsConnectFn({servers:this.natsUrl,name:"genie-omni-bridge",reconnect:!0,maxReconnectAttempts:-1,reconnectTimeWait:2000}),console.log("[omni-bridge] Connected to NATS"),await this.setupPg(),this.wireExecutorHooks(),this.subscribeOmniChannels(),this.startedAtMs=Date.now(),this.subscribePingChannel(),await this.claimPidfile(),this.armSignalCleanup(),this.idleCheckTimer=setInterval(()=>this.checkIdleSessions(),IDLE_CHECK_INTERVAL_MS),console.log(`[omni-bridge] Listening on omni.message.> (max_concurrent=${this.maxConcurrent}, idle_timeout=${this.idleTimeoutMs}ms)`)}async setupPg(){if(await this.probePg(),this.pgAvailable&&this.sql)this.sessionStore=new BridgeSessionStore(this.sql),await this.recoverSessions();if(this.executorType==="sdk"&&this.pgAvailable&&this.sql)this.queue=new OmniQueue(this.sql,(_req,msg)=>this.routeMessage(msg),this.queueConfig),await this.queue.recoverStale(),this.queue.start()}wireExecutorHooks(){this.executor.setSafePgCall(this.safePgCall.bind(this));let sc=this.sc,nc=this.nc;if(!nc)return;let publish=(topic,payload)=>{nc.publish(topic,sc.encode(payload))};this.executor.setNatsPublish(publish),this.heartbeatPublisher=new HeartbeatPublisher({publish})}subscribeOmniChannels(){if(!this.nc)return;this.sub=this.nc.subscribe("omni.message.>",{queue:"genie-bridge"}),this.processSubscription();let turnSubs=["omni.turn.open.>","omni.turn.done.>","omni.turn.nudge.>","omni.turn.timeout.>"];for(let topic of turnSubs){let sub=this.nc.subscribe(topic,{queue:"genie-bridge"});this.processTurnEvents(sub)}let sessionResetSub=this.nc.subscribe("omni.session.reset.>",{queue:"genie-bridge"});this.processSessionResetEvents(sessionResetSub)}subscribePingChannel(){if(!this.nc)return;this.pingSub=this.nc.subscribe(BRIDGE_PING_SUBJECT);let pingSub=this.pingSub,pingSc=this.sc,pingStart=this.startedAtMs;(async()=>{for await(let m of pingSub){let pong={ok:!0,pid:process.pid,uptimeMs:Date.now()-pingStart,subjects:["omni.message.>","omni.turn.open.>","omni.session.reset.>",BRIDGE_PING_SUBJECT]};try{m.respond(pingSc.encode(JSON.stringify(pong)))}catch{}}})().catch(()=>{})}async claimPidfile(){this.pidfilePath=getBridgePidfilePath();try{mkdirSync21(dirname19(this.pidfilePath),{recursive:!0}),this.evictStalePidfile(this.pidfilePath);let fd=openSync4(this.pidfilePath,"wx"),payload=JSON.stringify({pid:process.pid,startedAt:this.startedAtMs,subjects:["omni.message.>","omni.turn.open.>","omni.session.reset.>",BRIDGE_PING_SUBJECT],natsUrl:this.natsUrl});writeSync(fd,payload),closeSync4(fd)}catch(err){await this.rollbackStartOnPidfileError(err)}}evictStalePidfile(path3){if(!existsSync49(path3))return;let stalePid=null;try{let raw=readFileSync32(path3,"utf8"),parsed=JSON.parse(raw);if(typeof parsed.pid==="number"&&Number.isFinite(parsed.pid))stalePid=parsed.pid}catch{}if(stalePid!==null&&this.isPidAlive(stalePid))throw Error(`pidfile locked by PID ${stalePid}`);try{unlinkSync9(path3)}catch{}}isPidAlive(pid){try{return process.kill(pid,0),!0}catch(probeErr){return probeErr.code!=="ESRCH"}}async rollbackStartOnPidfileError(err){this.pidfilePath=null;let detail=err instanceof Error?err.message:String(err);try{if(this.pingSub)this.pingSub.unsubscribe()}catch{}this.pingSub=null;try{await this.nc?.drain()}catch{}throw this.nc=null,Error(`[omni-bridge] pidfile locked at ${getBridgePidfilePath()}: ${detail}`)}armSignalCleanup(){let onSignal=()=>{if(this.pidfilePath){try{unlinkSync9(this.pidfilePath)}catch{}this.pidfilePath=null}};process.once("SIGTERM",onSignal),process.once("SIGINT",onSignal),this.signalCleanup=()=>{process.removeListener("SIGTERM",onSignal),process.removeListener("SIGINT",onSignal)}}async stop(){if(!this.nc){console.log("[omni-bridge] Not running");return}if(console.log("[omni-bridge] Shutting down..."),this.queue)this.queue.stop(),this.queue=null;if(this.idleCheckTimer)clearInterval(this.idleCheckTimer),this.idleCheckTimer=null;if(this.heartbeatPublisher?.stopAll(),this.heartbeatPublisher=null,await this.shutdownActiveSessions(),this.unsubscribeChannels(),this.clearPidfileOnStop(),this.signalCleanup)this.signalCleanup(),this.signalCleanup=null;try{await this.nc.drain()}catch{}this.nc=null,this.sql=null,this.pgAvailable=!1,this.sessionStore=null,console.log("[omni-bridge] Stopped")}async shutdownActiveSessions(){for(let[key,entry2]of this.sessions){if(entry2.idleTimer)clearTimeout(entry2.idleTimer);if(entry2.spawning||!entry2.session)continue;if(entry2.session.executorType==="tmux"){console.log(`[omni-bridge] Detaching from tmux session ${key} (pane stays alive)`);continue}try{await this.executor.shutdown(entry2.session)}catch(err){console.warn(`[omni-bridge] Error shutting down session ${key}:`,err)}let closeId=entry2.pgBridgeSessionId;if(closeId&&this.sessionStore)await this.safePgCall("session_close_sdk",(sql)=>new BridgeSessionStore(sql).close(closeId),void 0)}this.sessions.clear()}unsubscribeChannels(){if(this.sub)this.sub.unsubscribe(),this.sub=null;if(this.pingSub){try{this.pingSub.unsubscribe()}catch{}this.pingSub=null}}clearPidfileOnStop(){if(!this.pidfilePath)return;try{unlinkSync9(this.pidfilePath)}catch{}this.pidfilePath=null}async status(){let now=Date.now(),activeFromPg=null,executorIds=[];if(this.pgAvailable&&this.sql){let rows=await this.safePgCall("status_active_count",async(sql)=>sql`
2633
+ `}}class TurnTracker{turns=new Map;open(sessionKey2,turnId,messageId){this.turns.set(sessionKey2,{turnId,sessionKey:sessionKey2,messageId,startedAt:Date.now(),closed:!1})}close(sessionKey2,action){let turn=this.turns.get(sessionKey2);if(turn&&!turn.closed)turn.closed=!0,turn.closedAction=action}isOpen(sessionKey2){let turn=this.turns.get(sessionKey2);return turn!==void 0&&!turn.closed}getTurnId(sessionKey2){return this.turns.get(sessionKey2)?.turnId}getByTurnId(turnId){for(let turn of this.turns.values())if(turn.turnId===turnId)return turn;return}delete(sessionKey2){this.turns.delete(sessionKey2)}}var exports_omni_bridge={};__export(exports_omni_bridge,{OmniBridge:()=>OmniBridge});import{closeSync as closeSync4,existsSync as existsSync49,mkdirSync as mkdirSync21,openSync as openSync4,readFileSync as readFileSync32,unlinkSync as unlinkSync9,writeSync}from"fs";import{dirname as dirname20}from"path";function withTimeout2(p,ms,label){return new Promise((resolve12,reject)=>{let timer2=setTimeout(()=>reject(Error(`${label} timed out after ${ms}ms`)),ms);timer2.unref?.(),p.then((v)=>{clearTimeout(timer2),resolve12(v)},(err)=>{clearTimeout(timer2),reject(err)})})}function isPgConnectionError(err){if(!err||typeof err!=="object")return!1;let e=err,code=e.code??"";if(["ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENOTFOUND","EPIPE","EHOSTUNREACH"].includes(code))return!0;let msg=e.message??String(err);return/ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EPIPE|connection terminated|connection closed|server closed the connection|the database system is shutting down/i.test(msg)}class OmniBridge{nc=null;sub=null;executor;turnTracker=new TurnTracker;heartbeatPublisher=null;sessions=new Map;messageQueue=[];recentMessageIds=new Map;idleCheckTimer=null;sc=import_nats4.StringCodec();sql=null;pgAvailable=!1;pgProvider;natsConnectFn;queueConfig;queue=null;sessionStore=null;natsUrl;idleTimeoutMs;maxConcurrent;executorType;pidfilePath=null;startedAtMs=0;pingSub=null;signalCleanup=null;constructor(config={}){if(this.natsUrl=config.natsUrl??process.env.GENIE_NATS_URL??DEFAULT_NATS_URL2,this.idleTimeoutMs=config.idleTimeoutMs??(process.env.GENIE_IDLE_TIMEOUT_MS?Number(process.env.GENIE_IDLE_TIMEOUT_MS):DEFAULT_IDLE_TIMEOUT_MS2),this.maxConcurrent=config.maxConcurrent??(process.env.GENIE_MAX_CONCURRENT?Number(process.env.GENIE_MAX_CONCURRENT):DEFAULT_MAX_CONCURRENT),this.pgProvider=config.pgProvider??(async()=>{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return await getConnection2()}),this.natsConnectFn=config.natsConnectFn??import_nats4.connect,this.queueConfig=config.queue??{},this.executorType=resolveExecutorType(config.executorType),this.executorType==="sdk")this.executor=new ClaudeSdkOmniExecutor;else this.executor=new ClaudeCodeOmniExecutor}async start(){if(this.nc){console.log("[omni-bridge] Already running");return}console.log(`[omni-bridge] Connecting to NATS at ${this.natsUrl}...`),this.nc=await this.natsConnectFn({servers:this.natsUrl,name:"genie-omni-bridge",reconnect:!0,maxReconnectAttempts:-1,reconnectTimeWait:2000}),console.log("[omni-bridge] Connected to NATS"),await this.setupPg(),this.wireExecutorHooks(),this.subscribeOmniChannels(),this.startedAtMs=Date.now(),this.subscribePingChannel(),await this.claimPidfile(),this.armSignalCleanup(),this.idleCheckTimer=setInterval(()=>this.checkIdleSessions(),IDLE_CHECK_INTERVAL_MS),console.log(`[omni-bridge] Listening on omni.message.> (max_concurrent=${this.maxConcurrent}, idle_timeout=${this.idleTimeoutMs}ms)`)}async setupPg(){if(await this.probePg(),this.pgAvailable&&this.sql)this.sessionStore=new BridgeSessionStore(this.sql),await this.recoverSessions();if(this.executorType==="sdk"&&this.pgAvailable&&this.sql)this.queue=new OmniQueue(this.sql,(_req,msg)=>this.routeMessage(msg),this.queueConfig),await this.queue.recoverStale(),this.queue.start()}wireExecutorHooks(){this.executor.setSafePgCall(this.safePgCall.bind(this));let sc=this.sc,nc=this.nc;if(!nc)return;let publish=(topic,payload)=>{nc.publish(topic,sc.encode(payload))};this.executor.setNatsPublish(publish),this.heartbeatPublisher=new HeartbeatPublisher({publish})}subscribeOmniChannels(){if(!this.nc)return;this.sub=this.nc.subscribe("omni.message.>",{queue:"genie-bridge"}),this.processSubscription();let turnSubs=["omni.turn.open.>","omni.turn.done.>","omni.turn.nudge.>","omni.turn.timeout.>"];for(let topic of turnSubs){let sub=this.nc.subscribe(topic,{queue:"genie-bridge"});this.processTurnEvents(sub)}let sessionResetSub=this.nc.subscribe("omni.session.reset.>",{queue:"genie-bridge"});this.processSessionResetEvents(sessionResetSub)}subscribePingChannel(){if(!this.nc)return;this.pingSub=this.nc.subscribe(BRIDGE_PING_SUBJECT);let pingSub=this.pingSub,pingSc=this.sc,pingStart=this.startedAtMs;(async()=>{for await(let m of pingSub){let pong={ok:!0,pid:process.pid,uptimeMs:Date.now()-pingStart,subjects:["omni.message.>","omni.turn.open.>","omni.session.reset.>",BRIDGE_PING_SUBJECT]};try{m.respond(pingSc.encode(JSON.stringify(pong)))}catch{}}})().catch(()=>{})}async claimPidfile(){this.pidfilePath=getBridgePidfilePath();try{mkdirSync21(dirname20(this.pidfilePath),{recursive:!0}),this.evictStalePidfile(this.pidfilePath);let fd=openSync4(this.pidfilePath,"wx"),payload=JSON.stringify({pid:process.pid,startedAt:this.startedAtMs,subjects:["omni.message.>","omni.turn.open.>","omni.session.reset.>",BRIDGE_PING_SUBJECT],natsUrl:this.natsUrl});writeSync(fd,payload),closeSync4(fd)}catch(err){await this.rollbackStartOnPidfileError(err)}}evictStalePidfile(path3){if(!existsSync49(path3))return;let stalePid=null;try{let raw=readFileSync32(path3,"utf8"),parsed=JSON.parse(raw);if(typeof parsed.pid==="number"&&Number.isFinite(parsed.pid))stalePid=parsed.pid}catch{}if(stalePid!==null&&this.isPidAlive(stalePid))throw Error(`pidfile locked by PID ${stalePid}`);try{unlinkSync9(path3)}catch{}}isPidAlive(pid){try{return process.kill(pid,0),!0}catch(probeErr){return probeErr.code!=="ESRCH"}}async rollbackStartOnPidfileError(err){this.pidfilePath=null;let detail=err instanceof Error?err.message:String(err);try{if(this.pingSub)this.pingSub.unsubscribe()}catch{}this.pingSub=null;try{await this.nc?.drain()}catch{}throw this.nc=null,Error(`[omni-bridge] pidfile locked at ${getBridgePidfilePath()}: ${detail}`)}armSignalCleanup(){let onSignal=()=>{if(this.pidfilePath){try{unlinkSync9(this.pidfilePath)}catch{}this.pidfilePath=null}};process.once("SIGTERM",onSignal),process.once("SIGINT",onSignal),this.signalCleanup=()=>{process.removeListener("SIGTERM",onSignal),process.removeListener("SIGINT",onSignal)}}async stop(){if(!this.nc){console.log("[omni-bridge] Not running");return}if(console.log("[omni-bridge] Shutting down..."),this.queue)this.queue.stop(),this.queue=null;if(this.idleCheckTimer)clearInterval(this.idleCheckTimer),this.idleCheckTimer=null;if(this.heartbeatPublisher?.stopAll(),this.heartbeatPublisher=null,await this.shutdownActiveSessions(),this.unsubscribeChannels(),this.clearPidfileOnStop(),this.signalCleanup)this.signalCleanup(),this.signalCleanup=null;try{await this.nc.drain()}catch{}this.nc=null,this.sql=null,this.pgAvailable=!1,this.sessionStore=null,console.log("[omni-bridge] Stopped")}async shutdownActiveSessions(){for(let[key,entry2]of this.sessions){if(entry2.idleTimer)clearTimeout(entry2.idleTimer);if(entry2.spawning||!entry2.session)continue;if(entry2.session.executorType==="tmux"){console.log(`[omni-bridge] Detaching from tmux session ${key} (pane stays alive)`);continue}try{await this.executor.shutdown(entry2.session)}catch(err){console.warn(`[omni-bridge] Error shutting down session ${key}:`,err)}let closeId=entry2.pgBridgeSessionId;if(closeId&&this.sessionStore)await this.safePgCall("session_close_sdk",(sql)=>new BridgeSessionStore(sql).close(closeId),void 0)}this.sessions.clear()}unsubscribeChannels(){if(this.sub)this.sub.unsubscribe(),this.sub=null;if(this.pingSub){try{this.pingSub.unsubscribe()}catch{}this.pingSub=null}}clearPidfileOnStop(){if(!this.pidfilePath)return;try{unlinkSync9(this.pidfilePath)}catch{}this.pidfilePath=null}async status(){let now=Date.now(),activeFromPg=null,executorIds=[];if(this.pgAvailable&&this.sql){let rows=await this.safePgCall("status_active_count",async(sql)=>sql`
2634
2634
  SELECT id FROM executors
2635
2635
  WHERE ended_at IS NULL AND metadata->>'source' = 'omni'
2636
- `,null);if(rows)activeFromPg=rows.length,executorIds=rows.map((r)=>r.id)}let pgQueue=null;if(this.queue)pgQueue=await this.safePgCall("status_queue_stats",(_sql)=>this.queue?.stats()??Promise.resolve(null),null);return{connected:this.nc!==null,natsUrl:this.natsUrl,pgAvailable:this.pgAvailable,activeSessions:activeFromPg??this.sessions.size,maxConcurrent:this.maxConcurrent,idleTimeoutMs:this.idleTimeoutMs,queueDepth:pgQueue?pgQueue.pending+pgQueue.processing:this.messageQueue.length,executorType:this.executorType,executorIds,pgQueue,sessions:Array.from(this.sessions.entries()).map(([key,entry2])=>({id:key,agentName:entry2.session.agentName,chatId:entry2.session.chatId,instanceId:entry2.instanceId,executorType:entry2.session.executorType,spawning:entry2.spawning,idleMs:now-entry2.session.lastActivityAt,bufferSize:entry2.buffer.length}))}}async probePg(){try{let sql=await withTimeout2(this.pgProvider(),PG_STARTUP_PROBE_TIMEOUT_MS,"PG provider startup");await withTimeout2(Promise.resolve(sql`SELECT 1`),PG_STARTUP_PROBE_TIMEOUT_MS,"PG SELECT 1 probe"),this.sql=sql,this.pgAvailable=!0,console.log("[omni-bridge] PG reachable \u2014 session recovery enabled")}catch(err){this.sql=null,this.pgAvailable=!1;let msg=err instanceof Error?err.message:String(err);if(isPgConnectionError(err)){console.warn(`[omni-bridge] PG unavailable \u2014 session recovery disabled (${msg})`);return}throw Error(`[omni-bridge] PG schema mismatch or setup error: ${msg}. ${"Run `bun run migrate` (or the equivalent migration command) and retry."}`)}}async recoverSessions(){if(!this.sessionStore)return;let orphanedCount=await this.safePgCall("recover_orphan_all",(sql)=>new BridgeSessionStore(sql).markAllOrphaned(),0);if(orphanedCount>0)console.log(`[omni-bridge] Startup cleanup: orphaned ${orphanedCount} stale session(s) from previous run`)}async safePgCall(op,fn,fallback,ctx){if(!this.pgAvailable||!this.sql)return fallback;let sql=this.sql;try{return await withTimeout2(fn(sql),PG_RUNTIME_QUERY_TIMEOUT_MS,`safePgCall(${op})`)}catch(err){let msg=err instanceof Error?err.message:String(err),execPart=ctx?.executorId?` executor_id=${ctx.executorId}`:"",chatPart=ctx?.chatId?` chat_id=${ctx.chatId}`:"";if(console.warn(`[omni-bridge] safePgCall(${op}) failed${execPart}${chatPart}: ${msg}`),isPgConnectionError(err))this.pgAvailable=!1,this.sql=null,console.warn("[omni-bridge] PG connection lost \u2014 switching to degraded mode");return fallback}}fillSubjectMetadata(parsed,subject){let parts=subject.split(".");if(parts.length<4)return;parsed.instanceId=parsed.instanceId||parts[2],parsed.chatId=parsed.chatId||parts[3]}isDuplicateMessage(messageId){if(!messageId)return!1;if(this.recentMessageIds.has(messageId))return!0;if(this.recentMessageIds.set(messageId,Date.now()),this.recentMessageIds.size>1000){let cutoff=Date.now()-60000;for(let[id,ts3]of this.recentMessageIds)if(ts3<cutoff)this.recentMessageIds.delete(id)}return!1}async dispatchMessage(parsed){if(this.queue){let env=parsed.env??{};await this.queue.enqueue(parsed,env);return}let key=`${parsed.agent}:${parsed.chatId}`,hasSession=this.sessions.has(key);console.log(`[omni-bridge] Routing message for ${key} (hasSession=${hasSession}, queue=${!!this.queue})`),await this.routeMessage(parsed),console.log(`[omni-bridge] routeMessage done for ${key}`)}async processSubscription(){if(!this.sub)return;for await(let msg of this.sub)try{let data=this.sc.decode(msg.data),parsed=JSON.parse(data);this.fillSubjectMetadata(parsed,msg.subject),console.log(`[omni-bridge] NATS message received: ${msg.subject} agent=${parsed.agent} chat=${parsed.chatId}`);let messageId=parsed.messageId;if(this.isDuplicateMessage(messageId)){console.log(`[omni-bridge] Dedup: skipping duplicate messageId=${messageId}`);continue}if(!parsed.chatId||!parsed.agent){console.warn("[omni-bridge] Dropping message: missing chatId or agent",msg.subject);continue}await this.dispatchMessage(parsed)}catch(err){console.error("[omni-bridge] Error processing message:",err)}}async processTurnEvents(sub){for await(let msg of sub)try{let payload=JSON.parse(this.sc.decode(msg.data)),parts=msg.subject.split("."),eventType=parts[2],instanceId=parts[3],chatId=parts.slice(4).join(".");console.log(`[omni-bridge] Turn event: ${eventType} instance=${instanceId} chat=${chatId}`);let sessionKey2=this.findSessionKey(instanceId,chatId);if(!sessionKey2&&payload.turnId){if(sessionKey2=this.findSessionKeyByTurnId(payload.turnId),sessionKey2)console.log(`[omni-bridge] Matched session via turnId fallback: ${sessionKey2}`)}if(sessionKey2)await this.routeTurnEvent(eventType,sessionKey2,payload);else console.log(`[omni-bridge] No session found for turn.${eventType} (instance=${instanceId}, chat=${chatId})`)}catch(err){console.warn("[omni-bridge] Error processing turn event:",err)}}async routeTurnEvent(eventType,sessionKey2,payload){switch(eventType){case"open":this.turnTracker.open(sessionKey2,payload.turnId,payload.messageId),this.startHeartbeat(sessionKey2,payload);break;case"done":this.turnTracker.close(sessionKey2,payload.action),this.heartbeatPublisher?.stop(sessionKey2),await this.handleTurnDone(sessionKey2);break;case"nudge":await this.handleTurnNudge(sessionKey2,payload.message);break;case"timeout":this.heartbeatPublisher?.stop(sessionKey2),await this.handleTurnTimeout(sessionKey2);break}}startHeartbeat(sessionKey2,payload){let publisher=this.heartbeatPublisher;if(!publisher)return;let entry2=this.sessions.get(sessionKey2);if(!entry2)return;let turnId=payload.turnId;if(!turnId)return;publisher.start(sessionKey2,{instanceId:entry2.instanceId,chatId:entry2.session?.chatId??"",turnId,isBusy:async()=>{let live=this.sessions.get(sessionKey2);if(!live?.session)return!1;try{return await this.executor.isBusy(live.session)}catch{return!1}}})}findSessionKeyByTurnId(turnId){for(let[key]of this.sessions)if(this.turnTracker.getTurnId(key)===turnId)return key;return}chatIdMap=new Map;findSessionKey(instanceId,chatId){let resolvedChatId=this.chatIdMap.get(chatId);for(let[key,entry2]of this.sessions){if(entry2.instanceId!==instanceId)continue;if(entry2.session?.chatId===chatId)return key;if(resolvedChatId&&entry2.session?.chatId===resolvedChatId)return key;if(entry2.spawning&&key.endsWith(`:${chatId}`))return key;if(resolvedChatId&&entry2.spawning&&key.endsWith(`:${resolvedChatId}`))return key}return}async handleTurnNudge(sessionKey2,nudgeText){let entry2=this.sessions.get(sessionKey2);if(!entry2?.session)return;try{await this.executor.injectNudge(entry2.session,nudgeText)}catch(err){console.warn(`[omni-bridge] Failed to inject nudge for ${sessionKey2}:`,err)}}async processSessionResetEvents(sub){for await(let msg of sub)try{let parts=msg.subject.split(".");if(parts.length<5){console.warn(`[omni-bridge] Malformed session-reset subject: ${msg.subject}`);continue}let instanceId=parts[3],chatId=parts.slice(4).join("."),action;try{action=JSON.parse(this.sc.decode(msg.data)).action}catch{}await this.handleSessionReset(instanceId,chatId,action)}catch(err){console.warn("[omni-bridge] Error processing session reset event:",err)}}async handleSessionReset(instanceId,chatId,action){let sessionKey2=this.findSessionKey(instanceId,chatId);if(!sessionKey2){console.log(`[omni-bridge] Session reset for cold chat ${instanceId}/${chatId} \u2014 no-op`);return}let entry2=this.sessions.get(sessionKey2);if(!entry2)return;let actionTag=action?` (action=${action})`:"";if(entry2.spawning){console.log(`[omni-bridge] Session reset for spawning ${sessionKey2}${actionTag}, marking cancelled`),entry2.cancelled=!0,entry2.buffer=[],this.turnTracker.close(sessionKey2,"reset"),this.heartbeatPublisher?.stop(sessionKey2),await this.removeSession(sessionKey2),await this.drainQueue();return}if(!entry2.session)return;console.log(`[omni-bridge] Session reset for ${sessionKey2}${actionTag}, evicting`),this.turnTracker.close(sessionKey2,"reset"),this.heartbeatPublisher?.stop(sessionKey2);try{await this.executor.shutdown(entry2.session)}catch(err){console.warn(`[omni-bridge] Error shutting down reset session ${sessionKey2}:`,err)}await this.removeSession(sessionKey2),await this.drainQueue()}async handleTurnDone(sessionKey2){if(!this.sessions.get(sessionKey2)?.session)return;console.log(`[omni-bridge] Turn done for ${sessionKey2}, session stays alive for next message`),this.resetIdleTimer(sessionKey2)}async handleTurnTimeout(sessionKey2){let entry2=this.sessions.get(sessionKey2);if(!entry2?.session)return;console.warn(`[omni-bridge] Turn timed out for ${sessionKey2}, evicting session`),this.turnTracker.close(sessionKey2,"timeout"),this.heartbeatPublisher?.stop(sessionKey2);try{await this.executor.shutdown(entry2.session)}catch(err){console.warn(`[omni-bridge] Error shutting down timed-out session ${sessionKey2}:`,err)}this.sessions.delete(sessionKey2)}async routeMessage(message){let key=`${message.agent}:${message.chatId}`,entry2=this.sessions.get(key);if(entry2){if(entry2.spawning){if(entry2.buffer.length<MAX_BUFFER_PER_CHAT)entry2.buffer.push(message);else console.warn(`[omni-bridge] Buffer full (${MAX_BUFFER_PER_CHAT}) for ${key}, dropping message from ${message.sender}`),await this.publishBufferFullReply(message);return}if(await this.executor.isAlive(entry2.session)){await this.executor.deliver(entry2.session,message),this.resetIdleTimer(key);let bsId=entry2.pgBridgeSessionId;if(bsId&&this.sessionStore)this.safePgCall("session_activity",(sql)=>new BridgeSessionStore(sql).recordActivity(bsId),void 0,{chatId:message.chatId});return}await this.removeSession(key)}await this.spawnSession(message)}async spawnSession(message){let key=`${message.agent}:${message.chatId}`,existing=this.sessions.get(key);if(existing){if(existing.buffer.length<MAX_BUFFER_PER_CHAT)existing.buffer.push(message),console.log(`[omni-bridge] Buffered message for existing session ${key} (buffer=${existing.buffer.length})`);return}if(this.sessions.size>=this.maxConcurrent){this.messageQueue.push(message),await this.publishAutoReply(message),console.log(`[omni-bridge] Max concurrent (${this.maxConcurrent}) reached, queued message for ${key}`);return}let placeholder={session:null,instanceId:message.instanceId,spawning:!0,buffer:[],idleTimer:null};this.sessions.set(key,placeholder);try{let raw=message,payloadEnv=raw.env,spawnEnv={OMNI_API_KEY:payloadEnv?.OMNI_API_KEY??process.env.OMNI_API_KEY??"",OMNI_INSTANCE:payloadEnv?.OMNI_INSTANCE??message.instanceId,OMNI_CHAT:payloadEnv?.OMNI_CHAT??message.chatId,OMNI_MESSAGE:payloadEnv?.OMNI_MESSAGE??raw.messageId??"",OMNI_TURN_ID:payloadEnv?.OMNI_TURN_ID||"",OMNI_SENDER_NAME:payloadEnv?.OMNI_SENDER_NAME??message.sender??""};console.log(`[omni-bridge] Spawning session for ${key}...`);let session=await this.executor.spawn(message.agent,message.chatId,spawnEnv,message.content);if(placeholder.cancelled){console.log(`[omni-bridge] Spawn for ${key} completed but was cancelled by reset, shutting down`);try{await this.executor.shutdown(session)}catch(err){console.warn(`[omni-bridge] Error shutting down cancelled spawn for ${key}:`,err)}return}if(placeholder.session=session,placeholder.spawning=!1,this.sessionStore){let claudeSessionId=session.sdk?.claudeSessionId??session.tmux?.claudeSessionId,pgId=await this.safePgCall("session_create",(sql)=>new BridgeSessionStore(sql).create({instanceId:message.instanceId,chatId:message.chatId,agentName:message.agent,executorId:session.sdk?.executorId,tmuxPaneId:session.tmux?.paneId,claudeSessionId}),void 0,{chatId:message.chatId});if(pgId)placeholder.pgBridgeSessionId=pgId}for(let buffered of placeholder.buffer)await this.executor.deliver(session,buffered);placeholder.buffer=[],this.resetIdleTimer(key);let sessionTag=session.executorType==="tmux"?`(tmux pane=${session.tmux?.paneId})`:"(executor=sdk)";console.log(`[omni-bridge] Session active: ${key} ${sessionTag}`)}catch(err){console.error(`[omni-bridge] Failed to spawn session for ${key}:`,err);let lostMessages=[message,...placeholder.buffer];if(lostMessages.length>0)console.warn(`[omni-bridge] Re-queuing ${lostMessages.length} buffered message(s) from failed spawn for ${key}`),this.messageQueue.push(...lostMessages);this.sessions.delete(key)}}resetIdleTimer(key){let entry2=this.sessions.get(key);if(!entry2)return;if(entry2.idleTimer)clearTimeout(entry2.idleTimer);entry2.idleTimer=setTimeout(async()=>{console.log(`[omni-bridge] Idle timeout for ${key}, shutting down...`);try{await this.executor.shutdown(entry2.session)}catch{}await this.removeSession(key),await this.drainQueue()},this.idleTimeoutMs)}async checkIdleSessions(){let now=Date.now();for(let[key,entry2]of this.sessions){if(entry2.spawning)continue;if(!await this.executor.isAlive(entry2.session)){console.log(`[omni-bridge] Dead session detected: ${key}`),await this.removeSession(key);continue}let idleMs=now-entry2.session.lastActivityAt;if(idleMs>this.idleTimeoutMs){console.log(`[omni-bridge] Forcing idle shutdown: ${key} (idle ${Math.round(idleMs/1000)}s)`);try{await this.executor.shutdown(entry2.session)}catch{}await this.removeSession(key)}}}async removeSession(key){let entry2=this.sessions.get(key);if(entry2?.idleTimer)clearTimeout(entry2.idleTimer);this.heartbeatPublisher?.stop(key);let closeId=entry2?.pgBridgeSessionId;if(closeId&&this.sessionStore)await this.safePgCall("session_close",(sql)=>new BridgeSessionStore(sql).close(closeId),void 0);this.sessions.delete(key)}async drainQueue(){while(this.messageQueue.length>0){if(this.sessions.size>=this.maxConcurrent)break;let message=this.messageQueue.shift();if(message)await this.spawnSession(message)}}async publishBufferFullReply(message){if(!this.nc)return;let topic=`omni.reply.${message.instanceId}.${message.chatId}`,reply={content:"Fila de mensagens cheia, por favor aguarde e tente novamente.",agent:message.agent,chat_id:message.chatId,instance_id:message.instanceId,timestamp:new Date().toISOString(),auto_reply:!0};this.nc.publish(topic,this.sc.encode(JSON.stringify(reply)))}async publishAutoReply(message){if(!this.nc)return;let topic=`omni.reply.${message.instanceId}.${message.chatId}`,reply={content:"Aguarde um momento, estou atendendo outros clientes.",agent:message.agent,chat_id:message.chatId,instance_id:message.instanceId,timestamp:new Date().toISOString(),auto_reply:!0};this.nc.publish(topic,this.sc.encode(JSON.stringify(reply)))}}var import_nats4,DEFAULT_NATS_URL2="localhost:4222",DEFAULT_IDLE_TIMEOUT_MS2=900000,DEFAULT_MAX_CONCURRENT=20,MAX_BUFFER_PER_CHAT=50,IDLE_CHECK_INTERVAL_MS=30000,PG_STARTUP_PROBE_TIMEOUT_MS=5000,PG_RUNTIME_QUERY_TIMEOUT_MS=2000;var init_omni_bridge=__esm(()=>{init_bridge_status();init_executor_config();init_agent_heartbeat();init_claude_code2();init_claude_sdk2();import_nats4=__toESM(require_mod4(),1)});import{existsSync as existsSync50,mkdirSync as mkdirSync22,readFileSync as readFileSync33,readdirSync as readdirSync12,renameSync as renameSync8,statSync as statSync13,writeFileSync as writeFileSync19}from"fs";import{homedir as homedir40}from"os";import{dirname as dirname20,join as join62,resolve as resolvePath4}from"path";import{pathToFileURL}from"url";function scanDir(dirAbs){if(!existsSync50(dirAbs))return[];return readdirSync12(dirAbs).filter((name)=>name.endsWith(".ts")&&!name.startsWith("_")&&!name.endsWith(".test.ts")).map((name)=>join62(dirAbs,name)).filter((p)=>{try{return statSync13(p).isFile()}catch{return!1}})}function discoverHooks(opts){let home=homedir40(),discovered=[],teamsRoot=join62(home,".claude","teams");if(existsSync50(teamsRoot))for(let teamName of readdirSync12(teamsRoot)){if(teamName.startsWith("_"))continue;let teamHooksDir=join62(teamsRoot,teamName,"hooks");for(let path3 of scanDir(teamHooksDir))discovered.push({path:path3,scope:"team",teamName})}if(opts.repoRoot){let repoHooksDir=join62(opts.repoRoot,".genie","hooks"),repoRemoteUrl=opts.resolveRepoRemoteUrl?.(opts.repoRoot)??void 0;for(let path3 of scanDir(repoHooksDir))discovered.push({path:path3,scope:"repo",repoRemoteUrl})}let globalHooksDir=join62(home,".genie","hooks");for(let path3 of scanDir(globalHooksDir))discovered.push({path:path3,scope:"global"});return discovered}function quarantine(filePath,errorMessage){let dir=dirname20(filePath),quarantineDir=join62(dir,"_quarantine");if(!existsSync50(quarantineDir))mkdirSync22(quarantineDir,{recursive:!0});let basename10=filePath.split("/").pop()??"unknown.ts",target=join62(quarantineDir,basename10);try{renameSync8(filePath,target)}catch{}try{writeFileSync19(`${target}.error`,errorMessage,"utf-8")}catch{}return target}function validateHandler(imported){if(typeof imported!=="object"||imported===null)return"expected default export to be an object";let handler=imported;if(handler.version!=="1")return`unknown handler version: ${String(handler.version)} (expected '1')`;if(typeof handler.name!=="string"||handler.name.length===0)return"handler.name must be a non-empty string";if(typeof handler.event!=="string")return"handler.event must be a HookEventName string";if(typeof handler.priority!=="number"||Number.isNaN(handler.priority))return"handler.priority must be a finite number";if(typeof handler.fn!=="function")return"handler.fn must be a function";return null}async function loadExternalHooks(opts={}){let trustPath=opts.trustPath??defaultTrustPath(),trustFile;try{trustFile=readTrustFile(trustPath)}catch(err){let msg=err instanceof Error?err.message:String(err);return console.warn(`[hook-loader] trust file unreadable at ${trustPath}: ${msg} \u2014 refusing to load any external hooks`),[]}let importer=opts.importer??((url)=>import(url.href)),discovered=discoverHooks(opts),loaded=[],seenNames=new Map,outcomes=[];for(let source of discovered){let verify=verifyTrust(source.path,trustFile,{currentRepoRemoteUrl:source.repoRemoteUrl});if(!verify.trusted){outcomes.push({kind:"untrusted",reason:verify.reason,source});continue}let imported;try{imported=await importer(pathToFileURL(resolvePath4(source.path)))}catch(err){let msg=err instanceof Error?`${err.name}: ${err.message}`:String(err),quarantined=quarantine(source.path,msg);outcomes.push({kind:"broken",error:msg,source,quarantined});continue}let handlerCandidate=imported.default,validationError=validateHandler(handlerCandidate);if(validationError!==null){let quarantined=quarantine(source.path,validationError);outcomes.push({kind:"broken",error:validationError,source,quarantined});continue}let stamped={...handlerCandidate,source:source.scope,manifest_path:source.path},existing=seenNames.get(stamped.name);if(existing){if(console.warn(`[hook-loader] handler name collision: "${stamped.name}" registered from ${existing.path} (${existing.scope}) shadows ${source.path} (${source.scope})`),opts.strict)throw Error(`--strict-hooks: handler name collision on "${stamped.name}" between ${existing.path} and ${source.path}`);outcomes.push({kind:"shadowed",handler:stamped,source,shadowedBy:existing});continue}parseCapabilities(readFileSync33(source.path,"utf-8")),seenNames.set(stamped.name,source),loaded.push(stamped),outcomes.push({kind:"loaded",handler:stamped,source})}let builtins=getRegistry().filter((h)=>h.source==="builtin");return setRegistry([...builtins,...loaded]),outcomes}var init_loader=__esm(()=>{init_hooks();init_trust()});var exports_hook_socket={};__export(exports_hook_socket,{startHookSocket:()=>startHookSocket,defaultHookSocketPath:()=>defaultHookSocketPath});import{existsSync as existsSync51,unlinkSync as unlinkSync10}from"fs";import{mkdir as mkdir7}from"fs/promises";import{createServer,connect as netConnect}from"net";import{homedir as homedir41}from"os";import{dirname as dirname21,join as join63}from"path";function defaultHookSocketPath(){if(process.env.GENIE_HOOK_SOCK)return process.env.GENIE_HOOK_SOCK;let home=process.env.GENIE_HOME??join63(homedir41(),".genie");return join63(home,"hook.sock")}async function detectStaleAndCleanup(socketPath){if(!existsSync51(socketPath))return"clean";if(await new Promise((resolve12)=>{let probe=netConnect(socketPath),finish=(alive)=>{try{probe.destroy()}catch{}resolve12(alive)};probe.once("connect",()=>finish(!0)),probe.once("error",()=>finish(!1)),setTimeout(()=>finish(!1),200).unref()}))return"live";try{return unlinkSync10(socketPath),"stale-removed"}catch(err){throw Error(`Failed to remove stale hook socket at ${socketPath}: ${err.message}`)}}function parseFrame(acc,length){if(length===-1){if(acc.length<4)return{kind:"incomplete",length:-1};let declared=acc.readUInt32BE(0);if(declared>MAX_FRAME_BYTES2)return{kind:"error",reason:`frame length ${declared} exceeds MAX_FRAME_BYTES`};if(declared===0)return{kind:"done",body:Buffer.alloc(0)};if(acc.length>=4+declared)return{kind:"done",body:acc.subarray(4,4+declared)};return{kind:"incomplete",length:declared}}if(acc.length>=4+length)return{kind:"done",body:acc.subarray(4,4+length)};return{kind:"incomplete",length}}function readOneFrame(socket){return new Promise((resolve12,reject)=>{let acc=Buffer.alloc(0),length=-1,cleanup=()=>{socket.off("data",onData),socket.off("end",onEnd),socket.off("error",onError)},onData=(chunk)=>{acc=acc.length===0?Buffer.from(chunk):Buffer.concat([acc,Buffer.from(chunk)],acc.length+chunk.length);let result2=parseFrame(acc,length);if(result2.kind==="incomplete"){length=result2.length;return}if(cleanup(),result2.kind==="done")resolve12(result2.body);else reject(Error(result2.reason))},onEnd=()=>{cleanup(),reject(Error(`socket closed after ${acc.length} bytes (expected ${length===-1?"4+":4+length})`))},onError=(err)=>{cleanup(),reject(err)};socket.on("data",onData),socket.on("end",onEnd),socket.on("error",onError)})}function writeFrame(socket,payload){let body=Buffer.from(payload,"utf-8");if(body.length>MAX_FRAME_BYTES2){let empty=Buffer.alloc(4);socket.end(empty);return}let header=Buffer.alloc(4);header.writeUInt32BE(body.length,0),socket.end(Buffer.concat([header,body]))}async function handleConnection(socket){socket.setNoDelay(!0);try{let body=await readOneFrame(socket),stdin=body.length===0?"":body.toString("utf-8"),reply=await dispatch(stdin);writeFrame(socket,reply??"")}catch(err){try{writeFrame(socket,"")}catch{}if(process.env.GENIE_HOOK_SOCK_DEBUG==="1")console.warn(`[hook-socket] connection error: ${err.message}`)}}async function startHookSocket(options={}){if(process.env.GENIE_WIDE_EMIT===void 0)process.env.GENIE_WIDE_EMIT="1";let loaderOutcomes=[];if(options.loadExternal!==!1)loaderOutcomes=await loadExternalHooks({repoRoot:options.repoRoot,strict:options.strict}),summarizeLoaderOutcomes(loaderOutcomes);let socketPath=defaultHookSocketPath();await mkdir7(dirname21(socketPath),{recursive:!0});let state=await detectStaleAndCleanup(socketPath);if(state==="live")throw Error(`hook socket at ${socketPath} is already live \u2014 another genie serve daemon is running. Refusing to start.`);if(state==="stale-removed")console.log(`hook-socket: removed stale socket at ${socketPath}`);let liveSockets=new Set,server3=createServer((socket)=>{liveSockets.add(socket),socket.once("close",()=>liveSockets.delete(socket)),handleConnection(socket)});await new Promise((resolve12,reject)=>{let onError=(err)=>{server3.off("listening",onListening),reject(err)},onListening=()=>{server3.off("error",onError),resolve12()};server3.once("error",onError),server3.once("listening",onListening),server3.listen(socketPath)}),console.log(`hook-socket: listening at ${socketPath}`);let stopped=!1;return{path:socketPath,stop:async()=>{if(stopped)return;stopped=!0;for(let sock of liveSockets)try{sock.destroy()}catch{}if(liveSockets.clear(),await new Promise((resolve12)=>{server3.close(()=>resolve12())}),existsSync51(socketPath))try{unlinkSync10(socketPath)}catch{}},loaderOutcomes}}function summarizeLoaderOutcomes(outcomes){if(outcomes.length===0)return;let loaded=0,untrusted=0,broken=0,shadowed=0;for(let outcome of outcomes)if(outcome.kind==="loaded")loaded+=1;else if(outcome.kind==="untrusted")untrusted+=1;else if(outcome.kind==="broken")broken+=1;else shadowed+=1;let parts=[`hook-loader: ${loaded} loaded`];if(untrusted>0)parts.push(`${untrusted} untrusted`);if(broken>0)parts.push(`${broken} broken (quarantined)`);if(shadowed>0)parts.push(`${shadowed} shadowed`);console.log(parts.join(", "))}var MAX_FRAME_BYTES2=1048576;var init_hook_socket=__esm(()=>{init_hooks();init_loader()});var exports_serve={};__export(exports_serve,{writeStoppingLockSync:()=>writeStoppingLockSync,startTuiTmuxServer:()=>startTuiTmuxServer,startBrainServerIfEnabled:()=>startBrainServerIfEnabled,registerServeCommands:()=>registerServeCommands,isTuiSessionReady:()=>isTuiSessionReady,isStoppingLockActive:()=>isStoppingLockActive,isServeRunning:()=>isServeRunning,getTuiQuitBindingArgs:()=>getTuiQuitBindingArgs,getTuiKeybindings:()=>getTuiKeybindings,ensureTuiSession:()=>ensureTuiSession,clearStoppingLock:()=>clearStoppingLock,autoStartServe:()=>autoStartServe});import{execSync as execSync10,spawn as spawn4,spawnSync as spawnSync6}from"child_process";import{appendFileSync as appendFileSync5,closeSync as closeSync5,existsSync as existsSync52,mkdirSync as mkdirSync23,openSync as openSync5,readFileSync as readFileSync34,unlinkSync as unlinkSync11,writeFileSync as writeFileSync20,writeSync as writeSync2}from"fs";import{homedir as homedir42}from"os";import{dirname as dirname22,join as join64}from"path";function genieHome3(){return process.env.GENIE_HOME??join64(homedir42(),".genie")}function servePidPath(){return join64(genieHome3(),"serve.pid")}function serveStartupStatusPath(){return join64(genieHome3(),"state",`serve-startup-${process.pid}-${Date.now()}.json`)}function readServePid(){let path3=servePidPath();if(!existsSync52(path3))return null;let raw=readFileSync34(path3,"utf-8").trim();if(raw==="")return null;let sepIdx=raw.indexOf(":");if(sepIdx<0){let pid2=Number.parseInt(raw,10);if(Number.isNaN(pid2)||pid2<=0)return null;return{pid:pid2,startTime:null}}let pidPart=raw.slice(0,sepIdx),startTimePart=raw.slice(sepIdx+1).trim(),pid=Number.parseInt(pidPart,10);if(Number.isNaN(pid)||pid<=0)return null;return{pid,startTime:startTimePart===""||startTimePart==="unknown"?null:startTimePart}}function removeServePid(){let path3=servePidPath();if(!existsSync52(path3))return;try{let current=readServePid();if(current&&current.pid!==process.pid)return;unlinkSync11(path3)}catch{}}function isProcessAlive(pid){try{return process.kill(pid,0),!0}catch{return!1}}function stoppingLockPath(){return join64(genieHome3(),"serve.stopping.lock")}function writeStoppingLockSync(ttlMs=STOPPING_LOCK_TTL_MS){mkdirSync23(genieHome3(),{recursive:!0}),writeFileSync20(stoppingLockPath(),String(Date.now()+ttlMs),"utf-8")}function clearStoppingLock(){try{unlinkSync11(stoppingLockPath())}catch{}}function isStoppingLockActive(){let path3=stoppingLockPath();if(!existsSync52(path3))return!1;let raw;try{raw=readFileSync34(path3,"utf-8").trim()}catch{return!1}let expiresAt=Number.parseInt(raw,10);if(raw===""||Number.isNaN(expiresAt)||expiresAt<=Date.now())return clearStoppingLock(),!1;return!0}function tuiTmuxConf(){return[join64(genieHome3(),"tui-tmux.conf")].find((p)=>existsSync52(p))??"/dev/null"}function tuiTmux(subcmd){return`${tmuxBin()} -L genie-tui -f ${tuiTmuxConf()} ${subcmd}`}function isGenieTmuxRunning(){try{return execSync10(genieTmuxCmd("list-sessions"),{stdio:"ignore"}),!0}catch{return!1}}function getTuiKeybindings(sessionName=TUI_SESSION){return[`bind-key -T root Tab if-shell "[ '#{pane_index}' = '0' ]" "select-pane -t ${sessionName}:0.1" "select-pane -t ${sessionName}:0.0"`,`bind-key -T root C-1 select-pane -t ${sessionName}:0.0`,`bind-key -T root C-2 select-pane -t ${sessionName}:0.1`,`bind-key -T root C-b if-shell "[ $(tmux display-message -p '#\\{pane_width\\}' -t ${sessionName}:0.0) -gt 5 ]" "resize-pane -t ${sessionName}:0.0 -x 0" "resize-pane -t ${sessionName}:0.0 -x ${NAV_WIDTH}"`,`bind-key -T root C-t select-pane -t ${sessionName}:0.0 \\; send-keys -t ${sessionName}:0.0 C-t`,"bind-key -T root C-d detach-client",`bind-key -T root C-q select-pane -t ${sessionName}:0.0 \\; send-keys -t ${sessionName}:0.0 C-q`]}function getTuiQuitBindingArgs(sessionName=TUI_SESSION){return["bind-key","-T","root","C-q","select-pane","-t",`${sessionName}:0.0`,"\\;","send-keys","-t",`${sessionName}:0.0`,"C-q"]}function applyTuiStyle(){let cmds=[`set-option -t ${TUI_SESSION} pane-border-style 'fg=${TUI_STYLE.inactiveBorder}'`,`set-option -t ${TUI_SESSION} pane-active-border-style 'fg=${TUI_STYLE.activeBorder}'`,...process.env.GENIE_TMUX_MOUSE!=="off"?[`set-option -t ${TUI_SESSION} mouse on`]:[],`set-option -t ${TUI_SESSION} status off`,`set-option -t ${TUI_SESSION} pane-border-status off`];for(let cmd of cmds)try{execSync10(tuiTmux(cmd),{stdio:"ignore"})}catch{}}function setupTuiKeybindings(){for(let cmd of getTuiKeybindings())try{if(cmd.startsWith("bind-key -T root C-q "))spawnSync6(tmuxBin(),["-L","genie-tui","-f",tuiTmuxConf(),...getTuiQuitBindingArgs()],{stdio:"ignore"});else execSync10(tuiTmux(cmd),{stdio:"ignore"})}catch{}}function runTuiTmuxCapturing(cmd){try{return execSync10(tuiTmux(cmd),{encoding:"utf-8",stdio:["ignore","pipe","pipe"]})}catch(err){let e=err,stderr=typeof e.stderr==="string"?e.stderr:e.stderr?.toString("utf-8"),stdout=typeof e.stdout==="string"?e.stdout:e.stdout?.toString("utf-8"),detail=(stderr??stdout??e.message??"unknown tmux error").trim();throw Error(`tmux ${cmd}: ${detail}`)}}function logTuiStartupFailure(message){try{let home=genieHome3(),logsDir=join64(home,"logs");mkdirSync23(logsDir,{recursive:!0});let crashLog=join64(logsDir,"tui-crash.log"),line=`[startTuiTmuxServer] ${new Date().toISOString()} ${message.replace(/\s+/g," ").trim()}
2636
+ `,null);if(rows)activeFromPg=rows.length,executorIds=rows.map((r)=>r.id)}let pgQueue=null;if(this.queue)pgQueue=await this.safePgCall("status_queue_stats",(_sql)=>this.queue?.stats()??Promise.resolve(null),null);return{connected:this.nc!==null,natsUrl:this.natsUrl,pgAvailable:this.pgAvailable,activeSessions:activeFromPg??this.sessions.size,maxConcurrent:this.maxConcurrent,idleTimeoutMs:this.idleTimeoutMs,queueDepth:pgQueue?pgQueue.pending+pgQueue.processing:this.messageQueue.length,executorType:this.executorType,executorIds,pgQueue,sessions:Array.from(this.sessions.entries()).map(([key,entry2])=>({id:key,agentName:entry2.session.agentName,chatId:entry2.session.chatId,instanceId:entry2.instanceId,executorType:entry2.session.executorType,spawning:entry2.spawning,idleMs:now-entry2.session.lastActivityAt,bufferSize:entry2.buffer.length}))}}async probePg(){try{let sql=await withTimeout2(this.pgProvider(),PG_STARTUP_PROBE_TIMEOUT_MS,"PG provider startup");await withTimeout2(Promise.resolve(sql`SELECT 1`),PG_STARTUP_PROBE_TIMEOUT_MS,"PG SELECT 1 probe"),this.sql=sql,this.pgAvailable=!0,console.log("[omni-bridge] PG reachable \u2014 session recovery enabled")}catch(err){this.sql=null,this.pgAvailable=!1;let msg=err instanceof Error?err.message:String(err);if(isPgConnectionError(err)){console.warn(`[omni-bridge] PG unavailable \u2014 session recovery disabled (${msg})`);return}throw Error(`[omni-bridge] PG schema mismatch or setup error: ${msg}. ${"Run `bun run migrate` (or the equivalent migration command) and retry."}`)}}async recoverSessions(){if(!this.sessionStore)return;let orphanedCount=await this.safePgCall("recover_orphan_all",(sql)=>new BridgeSessionStore(sql).markAllOrphaned(),0);if(orphanedCount>0)console.log(`[omni-bridge] Startup cleanup: orphaned ${orphanedCount} stale session(s) from previous run`)}async safePgCall(op,fn,fallback,ctx){if(!this.pgAvailable||!this.sql)return fallback;let sql=this.sql;try{return await withTimeout2(fn(sql),PG_RUNTIME_QUERY_TIMEOUT_MS,`safePgCall(${op})`)}catch(err){let msg=err instanceof Error?err.message:String(err),execPart=ctx?.executorId?` executor_id=${ctx.executorId}`:"",chatPart=ctx?.chatId?` chat_id=${ctx.chatId}`:"";if(console.warn(`[omni-bridge] safePgCall(${op}) failed${execPart}${chatPart}: ${msg}`),isPgConnectionError(err))this.pgAvailable=!1,this.sql=null,console.warn("[omni-bridge] PG connection lost \u2014 switching to degraded mode");return fallback}}fillSubjectMetadata(parsed,subject){let parts=subject.split(".");if(parts.length<4)return;parsed.instanceId=parsed.instanceId||parts[2],parsed.chatId=parsed.chatId||parts[3]}isDuplicateMessage(messageId){if(!messageId)return!1;if(this.recentMessageIds.has(messageId))return!0;if(this.recentMessageIds.set(messageId,Date.now()),this.recentMessageIds.size>1000){let cutoff=Date.now()-60000;for(let[id,ts3]of this.recentMessageIds)if(ts3<cutoff)this.recentMessageIds.delete(id)}return!1}async dispatchMessage(parsed){if(this.queue){let env=parsed.env??{};await this.queue.enqueue(parsed,env);return}let key=`${parsed.agent}:${parsed.chatId}`,hasSession=this.sessions.has(key);console.log(`[omni-bridge] Routing message for ${key} (hasSession=${hasSession}, queue=${!!this.queue})`),await this.routeMessage(parsed),console.log(`[omni-bridge] routeMessage done for ${key}`)}async processSubscription(){if(!this.sub)return;for await(let msg of this.sub)try{let data=this.sc.decode(msg.data),parsed=JSON.parse(data);this.fillSubjectMetadata(parsed,msg.subject),console.log(`[omni-bridge] NATS message received: ${msg.subject} agent=${parsed.agent} chat=${parsed.chatId}`);let messageId=parsed.messageId;if(this.isDuplicateMessage(messageId)){console.log(`[omni-bridge] Dedup: skipping duplicate messageId=${messageId}`);continue}if(!parsed.chatId||!parsed.agent){console.warn("[omni-bridge] Dropping message: missing chatId or agent",msg.subject);continue}await this.dispatchMessage(parsed)}catch(err){console.error("[omni-bridge] Error processing message:",err)}}async processTurnEvents(sub){for await(let msg of sub)try{let payload=JSON.parse(this.sc.decode(msg.data)),parts=msg.subject.split("."),eventType=parts[2],instanceId=parts[3],chatId=parts.slice(4).join(".");console.log(`[omni-bridge] Turn event: ${eventType} instance=${instanceId} chat=${chatId}`);let sessionKey2=this.findSessionKey(instanceId,chatId);if(!sessionKey2&&payload.turnId){if(sessionKey2=this.findSessionKeyByTurnId(payload.turnId),sessionKey2)console.log(`[omni-bridge] Matched session via turnId fallback: ${sessionKey2}`)}if(sessionKey2)await this.routeTurnEvent(eventType,sessionKey2,payload);else console.log(`[omni-bridge] No session found for turn.${eventType} (instance=${instanceId}, chat=${chatId})`)}catch(err){console.warn("[omni-bridge] Error processing turn event:",err)}}async routeTurnEvent(eventType,sessionKey2,payload){switch(eventType){case"open":this.turnTracker.open(sessionKey2,payload.turnId,payload.messageId),this.startHeartbeat(sessionKey2,payload);break;case"done":this.turnTracker.close(sessionKey2,payload.action),this.heartbeatPublisher?.stop(sessionKey2),await this.handleTurnDone(sessionKey2);break;case"nudge":await this.handleTurnNudge(sessionKey2,payload.message);break;case"timeout":this.heartbeatPublisher?.stop(sessionKey2),await this.handleTurnTimeout(sessionKey2);break}}startHeartbeat(sessionKey2,payload){let publisher=this.heartbeatPublisher;if(!publisher)return;let entry2=this.sessions.get(sessionKey2);if(!entry2)return;let turnId=payload.turnId;if(!turnId)return;publisher.start(sessionKey2,{instanceId:entry2.instanceId,chatId:entry2.session?.chatId??"",turnId,isBusy:async()=>{let live=this.sessions.get(sessionKey2);if(!live?.session)return!1;try{return await this.executor.isBusy(live.session)}catch{return!1}}})}findSessionKeyByTurnId(turnId){for(let[key]of this.sessions)if(this.turnTracker.getTurnId(key)===turnId)return key;return}chatIdMap=new Map;findSessionKey(instanceId,chatId){let resolvedChatId=this.chatIdMap.get(chatId);for(let[key,entry2]of this.sessions){if(entry2.instanceId!==instanceId)continue;if(entry2.session?.chatId===chatId)return key;if(resolvedChatId&&entry2.session?.chatId===resolvedChatId)return key;if(entry2.spawning&&key.endsWith(`:${chatId}`))return key;if(resolvedChatId&&entry2.spawning&&key.endsWith(`:${resolvedChatId}`))return key}return}async handleTurnNudge(sessionKey2,nudgeText){let entry2=this.sessions.get(sessionKey2);if(!entry2?.session)return;try{await this.executor.injectNudge(entry2.session,nudgeText)}catch(err){console.warn(`[omni-bridge] Failed to inject nudge for ${sessionKey2}:`,err)}}async processSessionResetEvents(sub){for await(let msg of sub)try{let parts=msg.subject.split(".");if(parts.length<5){console.warn(`[omni-bridge] Malformed session-reset subject: ${msg.subject}`);continue}let instanceId=parts[3],chatId=parts.slice(4).join("."),action;try{action=JSON.parse(this.sc.decode(msg.data)).action}catch{}await this.handleSessionReset(instanceId,chatId,action)}catch(err){console.warn("[omni-bridge] Error processing session reset event:",err)}}async handleSessionReset(instanceId,chatId,action){let sessionKey2=this.findSessionKey(instanceId,chatId);if(!sessionKey2){console.log(`[omni-bridge] Session reset for cold chat ${instanceId}/${chatId} \u2014 no-op`);return}let entry2=this.sessions.get(sessionKey2);if(!entry2)return;let actionTag=action?` (action=${action})`:"";if(entry2.spawning){console.log(`[omni-bridge] Session reset for spawning ${sessionKey2}${actionTag}, marking cancelled`),entry2.cancelled=!0,entry2.buffer=[],this.turnTracker.close(sessionKey2,"reset"),this.heartbeatPublisher?.stop(sessionKey2),await this.removeSession(sessionKey2),await this.drainQueue();return}if(!entry2.session)return;console.log(`[omni-bridge] Session reset for ${sessionKey2}${actionTag}, evicting`),this.turnTracker.close(sessionKey2,"reset"),this.heartbeatPublisher?.stop(sessionKey2);try{await this.executor.shutdown(entry2.session)}catch(err){console.warn(`[omni-bridge] Error shutting down reset session ${sessionKey2}:`,err)}await this.removeSession(sessionKey2),await this.drainQueue()}async handleTurnDone(sessionKey2){if(!this.sessions.get(sessionKey2)?.session)return;console.log(`[omni-bridge] Turn done for ${sessionKey2}, session stays alive for next message`),this.resetIdleTimer(sessionKey2)}async handleTurnTimeout(sessionKey2){let entry2=this.sessions.get(sessionKey2);if(!entry2?.session)return;console.warn(`[omni-bridge] Turn timed out for ${sessionKey2}, evicting session`),this.turnTracker.close(sessionKey2,"timeout"),this.heartbeatPublisher?.stop(sessionKey2);try{await this.executor.shutdown(entry2.session)}catch(err){console.warn(`[omni-bridge] Error shutting down timed-out session ${sessionKey2}:`,err)}this.sessions.delete(sessionKey2)}async routeMessage(message){let key=`${message.agent}:${message.chatId}`,entry2=this.sessions.get(key);if(entry2){if(entry2.spawning){if(entry2.buffer.length<MAX_BUFFER_PER_CHAT)entry2.buffer.push(message);else console.warn(`[omni-bridge] Buffer full (${MAX_BUFFER_PER_CHAT}) for ${key}, dropping message from ${message.sender}`),await this.publishBufferFullReply(message);return}if(await this.executor.isAlive(entry2.session)){await this.executor.deliver(entry2.session,message),this.resetIdleTimer(key);let bsId=entry2.pgBridgeSessionId;if(bsId&&this.sessionStore)this.safePgCall("session_activity",(sql)=>new BridgeSessionStore(sql).recordActivity(bsId),void 0,{chatId:message.chatId});return}await this.removeSession(key)}await this.spawnSession(message)}async spawnSession(message){let key=`${message.agent}:${message.chatId}`,existing=this.sessions.get(key);if(existing){if(existing.buffer.length<MAX_BUFFER_PER_CHAT)existing.buffer.push(message),console.log(`[omni-bridge] Buffered message for existing session ${key} (buffer=${existing.buffer.length})`);return}if(this.sessions.size>=this.maxConcurrent){this.messageQueue.push(message),await this.publishAutoReply(message),console.log(`[omni-bridge] Max concurrent (${this.maxConcurrent}) reached, queued message for ${key}`);return}let placeholder={session:null,instanceId:message.instanceId,spawning:!0,buffer:[],idleTimer:null};this.sessions.set(key,placeholder);try{let raw=message,payloadEnv=raw.env,spawnEnv={OMNI_API_KEY:payloadEnv?.OMNI_API_KEY??process.env.OMNI_API_KEY??"",OMNI_INSTANCE:payloadEnv?.OMNI_INSTANCE??message.instanceId,OMNI_CHAT:payloadEnv?.OMNI_CHAT??message.chatId,OMNI_MESSAGE:payloadEnv?.OMNI_MESSAGE??raw.messageId??"",OMNI_TURN_ID:payloadEnv?.OMNI_TURN_ID||"",OMNI_SENDER_NAME:payloadEnv?.OMNI_SENDER_NAME??message.sender??""};console.log(`[omni-bridge] Spawning session for ${key}...`);let session=await this.executor.spawn(message.agent,message.chatId,spawnEnv,message.content);if(placeholder.cancelled){console.log(`[omni-bridge] Spawn for ${key} completed but was cancelled by reset, shutting down`);try{await this.executor.shutdown(session)}catch(err){console.warn(`[omni-bridge] Error shutting down cancelled spawn for ${key}:`,err)}return}if(placeholder.session=session,placeholder.spawning=!1,this.sessionStore){let claudeSessionId=session.sdk?.claudeSessionId??session.tmux?.claudeSessionId,pgId=await this.safePgCall("session_create",(sql)=>new BridgeSessionStore(sql).create({instanceId:message.instanceId,chatId:message.chatId,agentName:message.agent,executorId:session.sdk?.executorId,tmuxPaneId:session.tmux?.paneId,claudeSessionId}),void 0,{chatId:message.chatId});if(pgId)placeholder.pgBridgeSessionId=pgId}for(let buffered of placeholder.buffer)await this.executor.deliver(session,buffered);placeholder.buffer=[],this.resetIdleTimer(key);let sessionTag=session.executorType==="tmux"?`(tmux pane=${session.tmux?.paneId})`:"(executor=sdk)";console.log(`[omni-bridge] Session active: ${key} ${sessionTag}`)}catch(err){console.error(`[omni-bridge] Failed to spawn session for ${key}:`,err);let lostMessages=[message,...placeholder.buffer];if(lostMessages.length>0)console.warn(`[omni-bridge] Re-queuing ${lostMessages.length} buffered message(s) from failed spawn for ${key}`),this.messageQueue.push(...lostMessages);this.sessions.delete(key)}}resetIdleTimer(key){let entry2=this.sessions.get(key);if(!entry2)return;if(entry2.idleTimer)clearTimeout(entry2.idleTimer);entry2.idleTimer=setTimeout(async()=>{console.log(`[omni-bridge] Idle timeout for ${key}, shutting down...`);try{await this.executor.shutdown(entry2.session)}catch{}await this.removeSession(key),await this.drainQueue()},this.idleTimeoutMs)}async checkIdleSessions(){let now=Date.now();for(let[key,entry2]of this.sessions){if(entry2.spawning)continue;if(!await this.executor.isAlive(entry2.session)){console.log(`[omni-bridge] Dead session detected: ${key}`),await this.removeSession(key);continue}let idleMs=now-entry2.session.lastActivityAt;if(idleMs>this.idleTimeoutMs){console.log(`[omni-bridge] Forcing idle shutdown: ${key} (idle ${Math.round(idleMs/1000)}s)`);try{await this.executor.shutdown(entry2.session)}catch{}await this.removeSession(key)}}}async removeSession(key){let entry2=this.sessions.get(key);if(entry2?.idleTimer)clearTimeout(entry2.idleTimer);this.heartbeatPublisher?.stop(key);let closeId=entry2?.pgBridgeSessionId;if(closeId&&this.sessionStore)await this.safePgCall("session_close",(sql)=>new BridgeSessionStore(sql).close(closeId),void 0);this.sessions.delete(key)}async drainQueue(){while(this.messageQueue.length>0){if(this.sessions.size>=this.maxConcurrent)break;let message=this.messageQueue.shift();if(message)await this.spawnSession(message)}}async publishBufferFullReply(message){if(!this.nc)return;let topic=`omni.reply.${message.instanceId}.${message.chatId}`,reply={content:"Fila de mensagens cheia, por favor aguarde e tente novamente.",agent:message.agent,chat_id:message.chatId,instance_id:message.instanceId,timestamp:new Date().toISOString(),auto_reply:!0};this.nc.publish(topic,this.sc.encode(JSON.stringify(reply)))}async publishAutoReply(message){if(!this.nc)return;let topic=`omni.reply.${message.instanceId}.${message.chatId}`,reply={content:"Aguarde um momento, estou atendendo outros clientes.",agent:message.agent,chat_id:message.chatId,instance_id:message.instanceId,timestamp:new Date().toISOString(),auto_reply:!0};this.nc.publish(topic,this.sc.encode(JSON.stringify(reply)))}}var import_nats4,DEFAULT_NATS_URL2="localhost:4222",DEFAULT_IDLE_TIMEOUT_MS2=900000,DEFAULT_MAX_CONCURRENT=20,MAX_BUFFER_PER_CHAT=50,IDLE_CHECK_INTERVAL_MS=30000,PG_STARTUP_PROBE_TIMEOUT_MS=5000,PG_RUNTIME_QUERY_TIMEOUT_MS=2000;var init_omni_bridge=__esm(()=>{init_bridge_status();init_executor_config();init_agent_heartbeat();init_claude_code2();init_claude_sdk2();import_nats4=__toESM(require_mod4(),1)});import{existsSync as existsSync50,mkdirSync as mkdirSync22,readFileSync as readFileSync33,readdirSync as readdirSync12,renameSync as renameSync9,statSync as statSync13,writeFileSync as writeFileSync19}from"fs";import{homedir as homedir40}from"os";import{dirname as dirname21,join as join62,resolve as resolvePath4}from"path";import{pathToFileURL}from"url";function scanDir(dirAbs){if(!existsSync50(dirAbs))return[];return readdirSync12(dirAbs).filter((name)=>name.endsWith(".ts")&&!name.startsWith("_")&&!name.endsWith(".test.ts")).map((name)=>join62(dirAbs,name)).filter((p)=>{try{return statSync13(p).isFile()}catch{return!1}})}function discoverHooks(opts){let home=homedir40(),discovered=[],teamsRoot=join62(home,".claude","teams");if(existsSync50(teamsRoot))for(let teamName of readdirSync12(teamsRoot)){if(teamName.startsWith("_"))continue;let teamHooksDir=join62(teamsRoot,teamName,"hooks");for(let path3 of scanDir(teamHooksDir))discovered.push({path:path3,scope:"team",teamName})}if(opts.repoRoot){let repoHooksDir=join62(opts.repoRoot,".genie","hooks"),repoRemoteUrl=opts.resolveRepoRemoteUrl?.(opts.repoRoot)??void 0;for(let path3 of scanDir(repoHooksDir))discovered.push({path:path3,scope:"repo",repoRemoteUrl})}let globalHooksDir=join62(home,".genie","hooks");for(let path3 of scanDir(globalHooksDir))discovered.push({path:path3,scope:"global"});return discovered}function quarantine(filePath,errorMessage){let dir=dirname21(filePath),quarantineDir=join62(dir,"_quarantine");if(!existsSync50(quarantineDir))mkdirSync22(quarantineDir,{recursive:!0});let basename10=filePath.split("/").pop()??"unknown.ts",target=join62(quarantineDir,basename10);try{renameSync9(filePath,target)}catch{}try{writeFileSync19(`${target}.error`,errorMessage,"utf-8")}catch{}return target}function validateHandler(imported){if(typeof imported!=="object"||imported===null)return"expected default export to be an object";let handler=imported;if(handler.version!=="1")return`unknown handler version: ${String(handler.version)} (expected '1')`;if(typeof handler.name!=="string"||handler.name.length===0)return"handler.name must be a non-empty string";if(typeof handler.event!=="string")return"handler.event must be a HookEventName string";if(typeof handler.priority!=="number"||Number.isNaN(handler.priority))return"handler.priority must be a finite number";if(typeof handler.fn!=="function")return"handler.fn must be a function";return null}async function loadExternalHooks(opts={}){let trustPath=opts.trustPath??defaultTrustPath(),trustFile;try{trustFile=readTrustFile(trustPath)}catch(err){let msg=err instanceof Error?err.message:String(err);return console.warn(`[hook-loader] trust file unreadable at ${trustPath}: ${msg} \u2014 refusing to load any external hooks`),[]}let importer=opts.importer??((url)=>import(url.href)),discovered=discoverHooks(opts),loaded=[],seenNames=new Map,outcomes=[];for(let source of discovered){let verify=verifyTrust(source.path,trustFile,{currentRepoRemoteUrl:source.repoRemoteUrl});if(!verify.trusted){outcomes.push({kind:"untrusted",reason:verify.reason,source});continue}let imported;try{imported=await importer(pathToFileURL(resolvePath4(source.path)))}catch(err){let msg=err instanceof Error?`${err.name}: ${err.message}`:String(err),quarantined=quarantine(source.path,msg);outcomes.push({kind:"broken",error:msg,source,quarantined});continue}let handlerCandidate=imported.default,validationError=validateHandler(handlerCandidate);if(validationError!==null){let quarantined=quarantine(source.path,validationError);outcomes.push({kind:"broken",error:validationError,source,quarantined});continue}let stamped={...handlerCandidate,source:source.scope,manifest_path:source.path},existing=seenNames.get(stamped.name);if(existing){if(console.warn(`[hook-loader] handler name collision: "${stamped.name}" registered from ${existing.path} (${existing.scope}) shadows ${source.path} (${source.scope})`),opts.strict)throw Error(`--strict-hooks: handler name collision on "${stamped.name}" between ${existing.path} and ${source.path}`);outcomes.push({kind:"shadowed",handler:stamped,source,shadowedBy:existing});continue}parseCapabilities(readFileSync33(source.path,"utf-8")),seenNames.set(stamped.name,source),loaded.push(stamped),outcomes.push({kind:"loaded",handler:stamped,source})}let builtins=getRegistry().filter((h)=>h.source==="builtin");return setRegistry([...builtins,...loaded]),outcomes}var init_loader=__esm(()=>{init_hooks();init_trust()});var exports_hook_socket={};__export(exports_hook_socket,{startHookSocket:()=>startHookSocket,defaultHookSocketPath:()=>defaultHookSocketPath});import{existsSync as existsSync51,unlinkSync as unlinkSync10}from"fs";import{mkdir as mkdir6}from"fs/promises";import{createServer,connect as netConnect}from"net";import{homedir as homedir41}from"os";import{dirname as dirname22,join as join63}from"path";function defaultHookSocketPath(){if(process.env.GENIE_HOOK_SOCK)return process.env.GENIE_HOOK_SOCK;let home=process.env.GENIE_HOME??join63(homedir41(),".genie");return join63(home,"hook.sock")}async function detectStaleAndCleanup(socketPath){if(!existsSync51(socketPath))return"clean";if(await new Promise((resolve12)=>{let probe=netConnect(socketPath),finish=(alive)=>{try{probe.destroy()}catch{}resolve12(alive)};probe.once("connect",()=>finish(!0)),probe.once("error",()=>finish(!1)),setTimeout(()=>finish(!1),200).unref()}))return"live";try{return unlinkSync10(socketPath),"stale-removed"}catch(err){throw Error(`Failed to remove stale hook socket at ${socketPath}: ${err.message}`)}}function parseFrame(acc,length){if(length===-1){if(acc.length<4)return{kind:"incomplete",length:-1};let declared=acc.readUInt32BE(0);if(declared>MAX_FRAME_BYTES2)return{kind:"error",reason:`frame length ${declared} exceeds MAX_FRAME_BYTES`};if(declared===0)return{kind:"done",body:Buffer.alloc(0)};if(acc.length>=4+declared)return{kind:"done",body:acc.subarray(4,4+declared)};return{kind:"incomplete",length:declared}}if(acc.length>=4+length)return{kind:"done",body:acc.subarray(4,4+length)};return{kind:"incomplete",length}}function readOneFrame(socket){return new Promise((resolve12,reject)=>{let acc=Buffer.alloc(0),length=-1,cleanup=()=>{socket.off("data",onData),socket.off("end",onEnd),socket.off("error",onError)},onData=(chunk)=>{acc=acc.length===0?Buffer.from(chunk):Buffer.concat([acc,Buffer.from(chunk)],acc.length+chunk.length);let result2=parseFrame(acc,length);if(result2.kind==="incomplete"){length=result2.length;return}if(cleanup(),result2.kind==="done")resolve12(result2.body);else reject(Error(result2.reason))},onEnd=()=>{cleanup(),reject(Error(`socket closed after ${acc.length} bytes (expected ${length===-1?"4+":4+length})`))},onError=(err)=>{cleanup(),reject(err)};socket.on("data",onData),socket.on("end",onEnd),socket.on("error",onError)})}function writeFrame(socket,payload){let body=Buffer.from(payload,"utf-8");if(body.length>MAX_FRAME_BYTES2){let empty=Buffer.alloc(4);socket.end(empty);return}let header=Buffer.alloc(4);header.writeUInt32BE(body.length,0),socket.end(Buffer.concat([header,body]))}async function handleConnection(socket){socket.setNoDelay(!0);try{let body=await readOneFrame(socket),stdin=body.length===0?"":body.toString("utf-8"),reply=await dispatch(stdin);writeFrame(socket,reply??"")}catch(err){try{writeFrame(socket,"")}catch{}if(process.env.GENIE_HOOK_SOCK_DEBUG==="1")console.warn(`[hook-socket] connection error: ${err.message}`)}}async function startHookSocket(options={}){if(process.env.GENIE_WIDE_EMIT===void 0)process.env.GENIE_WIDE_EMIT="1";let loaderOutcomes=[];if(options.loadExternal!==!1)loaderOutcomes=await loadExternalHooks({repoRoot:options.repoRoot,strict:options.strict}),summarizeLoaderOutcomes(loaderOutcomes);let socketPath=defaultHookSocketPath();await mkdir6(dirname22(socketPath),{recursive:!0});let state=await detectStaleAndCleanup(socketPath);if(state==="live")throw Error(`hook socket at ${socketPath} is already live \u2014 another genie serve daemon is running. Refusing to start.`);if(state==="stale-removed")console.log(`hook-socket: removed stale socket at ${socketPath}`);let liveSockets=new Set,server3=createServer((socket)=>{liveSockets.add(socket),socket.once("close",()=>liveSockets.delete(socket)),handleConnection(socket)});await new Promise((resolve12,reject)=>{let onError=(err)=>{server3.off("listening",onListening),reject(err)},onListening=()=>{server3.off("error",onError),resolve12()};server3.once("error",onError),server3.once("listening",onListening),server3.listen(socketPath)}),console.log(`hook-socket: listening at ${socketPath}`);let stopped=!1;return{path:socketPath,stop:async()=>{if(stopped)return;stopped=!0;for(let sock of liveSockets)try{sock.destroy()}catch{}if(liveSockets.clear(),await new Promise((resolve12)=>{server3.close(()=>resolve12())}),existsSync51(socketPath))try{unlinkSync10(socketPath)}catch{}},loaderOutcomes}}function summarizeLoaderOutcomes(outcomes){if(outcomes.length===0)return;let loaded=0,untrusted=0,broken=0,shadowed=0;for(let outcome of outcomes)if(outcome.kind==="loaded")loaded+=1;else if(outcome.kind==="untrusted")untrusted+=1;else if(outcome.kind==="broken")broken+=1;else shadowed+=1;let parts=[`hook-loader: ${loaded} loaded`];if(untrusted>0)parts.push(`${untrusted} untrusted`);if(broken>0)parts.push(`${broken} broken (quarantined)`);if(shadowed>0)parts.push(`${shadowed} shadowed`);console.log(parts.join(", "))}var MAX_FRAME_BYTES2=1048576;var init_hook_socket=__esm(()=>{init_hooks();init_loader()});var exports_serve={};__export(exports_serve,{writeStoppingLockSync:()=>writeStoppingLockSync,startTuiTmuxServer:()=>startTuiTmuxServer,startBrainServerIfEnabled:()=>startBrainServerIfEnabled,registerServeCommands:()=>registerServeCommands,isTuiSessionReady:()=>isTuiSessionReady,isStoppingLockActive:()=>isStoppingLockActive,isServeRunning:()=>isServeRunning,getTuiQuitBindingArgs:()=>getTuiQuitBindingArgs,getTuiKeybindings:()=>getTuiKeybindings,ensureTuiSession:()=>ensureTuiSession,clearStoppingLock:()=>clearStoppingLock,autoStartServe:()=>autoStartServe});import{execSync as execSync10,spawn as spawn4,spawnSync as spawnSync6}from"child_process";import{appendFileSync as appendFileSync5,closeSync as closeSync5,existsSync as existsSync52,mkdirSync as mkdirSync23,openSync as openSync5,readFileSync as readFileSync34,unlinkSync as unlinkSync11,writeFileSync as writeFileSync20,writeSync as writeSync2}from"fs";import{homedir as homedir42}from"os";import{dirname as dirname23,join as join64}from"path";function genieHome3(){return process.env.GENIE_HOME??join64(homedir42(),".genie")}function servePidPath(){return join64(genieHome3(),"serve.pid")}function serveStartupStatusPath(){return join64(genieHome3(),"state",`serve-startup-${process.pid}-${Date.now()}.json`)}function readServePid(){let path3=servePidPath();if(!existsSync52(path3))return null;let raw=readFileSync34(path3,"utf-8").trim();if(raw==="")return null;let sepIdx=raw.indexOf(":");if(sepIdx<0){let pid2=Number.parseInt(raw,10);if(Number.isNaN(pid2)||pid2<=0)return null;return{pid:pid2,startTime:null}}let pidPart=raw.slice(0,sepIdx),startTimePart=raw.slice(sepIdx+1).trim(),pid=Number.parseInt(pidPart,10);if(Number.isNaN(pid)||pid<=0)return null;return{pid,startTime:startTimePart===""||startTimePart==="unknown"?null:startTimePart}}function removeServePid(){let path3=servePidPath();if(!existsSync52(path3))return;try{let current=readServePid();if(current&&current.pid!==process.pid)return;unlinkSync11(path3)}catch{}}function isProcessAlive(pid){try{return process.kill(pid,0),!0}catch{return!1}}function stoppingLockPath(){return join64(genieHome3(),"serve.stopping.lock")}function writeStoppingLockSync(ttlMs=STOPPING_LOCK_TTL_MS){mkdirSync23(genieHome3(),{recursive:!0}),writeFileSync20(stoppingLockPath(),String(Date.now()+ttlMs),"utf-8")}function clearStoppingLock(){try{unlinkSync11(stoppingLockPath())}catch{}}function isStoppingLockActive(){let path3=stoppingLockPath();if(!existsSync52(path3))return!1;let raw;try{raw=readFileSync34(path3,"utf-8").trim()}catch{return!1}let expiresAt=Number.parseInt(raw,10);if(raw===""||Number.isNaN(expiresAt)||expiresAt<=Date.now())return clearStoppingLock(),!1;return!0}function tuiTmuxConf(){return[join64(genieHome3(),"tui-tmux.conf")].find((p)=>existsSync52(p))??"/dev/null"}function tuiTmux(subcmd){return`${tmuxBin()} -L genie-tui -f ${tuiTmuxConf()} ${subcmd}`}function isGenieTmuxRunning(){try{return execSync10(genieTmuxCmd("list-sessions"),{stdio:"ignore"}),!0}catch{return!1}}function getTuiKeybindings(sessionName=TUI_SESSION){return[`bind-key -T root Tab if-shell "[ '#{pane_index}' = '0' ]" "select-pane -t ${sessionName}:0.1" "select-pane -t ${sessionName}:0.0"`,`bind-key -T root C-1 select-pane -t ${sessionName}:0.0`,`bind-key -T root C-2 select-pane -t ${sessionName}:0.1`,`bind-key -T root C-b if-shell "[ $(tmux display-message -p '#\\{pane_width\\}' -t ${sessionName}:0.0) -gt 5 ]" "resize-pane -t ${sessionName}:0.0 -x 0" "resize-pane -t ${sessionName}:0.0 -x ${NAV_WIDTH}"`,`bind-key -T root C-t select-pane -t ${sessionName}:0.0 \\; send-keys -t ${sessionName}:0.0 C-t`,"bind-key -T root C-d detach-client",`bind-key -T root C-q select-pane -t ${sessionName}:0.0 \\; send-keys -t ${sessionName}:0.0 C-q`]}function getTuiQuitBindingArgs(sessionName=TUI_SESSION){return["bind-key","-T","root","C-q","select-pane","-t",`${sessionName}:0.0`,"\\;","send-keys","-t",`${sessionName}:0.0`,"C-q"]}function applyTuiStyle(){let cmds=[`set-option -t ${TUI_SESSION} pane-border-style 'fg=${TUI_STYLE.inactiveBorder}'`,`set-option -t ${TUI_SESSION} pane-active-border-style 'fg=${TUI_STYLE.activeBorder}'`,...process.env.GENIE_TMUX_MOUSE!=="off"?[`set-option -t ${TUI_SESSION} mouse on`]:[],`set-option -t ${TUI_SESSION} status off`,`set-option -t ${TUI_SESSION} pane-border-status off`];for(let cmd of cmds)try{execSync10(tuiTmux(cmd),{stdio:"ignore"})}catch{}}function setupTuiKeybindings(){for(let cmd of getTuiKeybindings())try{if(cmd.startsWith("bind-key -T root C-q "))spawnSync6(tmuxBin(),["-L","genie-tui","-f",tuiTmuxConf(),...getTuiQuitBindingArgs()],{stdio:"ignore"});else execSync10(tuiTmux(cmd),{stdio:"ignore"})}catch{}}function runTuiTmuxCapturing(cmd){try{return execSync10(tuiTmux(cmd),{encoding:"utf-8",stdio:["ignore","pipe","pipe"]})}catch(err){let e=err,stderr=typeof e.stderr==="string"?e.stderr:e.stderr?.toString("utf-8"),stdout=typeof e.stdout==="string"?e.stdout:e.stdout?.toString("utf-8"),detail=(stderr??stdout??e.message??"unknown tmux error").trim();throw Error(`tmux ${cmd}: ${detail}`)}}function logTuiStartupFailure(message){try{let home=genieHome3(),logsDir=join64(home,"logs");mkdirSync23(logsDir,{recursive:!0});let crashLog=join64(logsDir,"tui-crash.log"),line=`[startTuiTmuxServer] ${new Date().toISOString()} ${message.replace(/\s+/g," ").trim()}
2637
2637
  `;appendFileSync5(crashLog,line)}catch{}}function freshCreateTuiSession(){runTuiTmuxCapturing(`new-session -d -s ${TUI_SESSION} -x 120 -y 40`),runTuiTmuxCapturing(`split-window -h -t ${TUI_SESSION}:0 -l ${120-NAV_WIDTH-1}`);let panes=execSync10(tuiTmux(`list-panes -t ${TUI_SESSION}:0 -F '#{pane_id}'`),{encoding:"utf-8"}).trim().split(`
2638
2638
  `);applyTuiStyle(),setupTuiKeybindings();try{execSync10(tuiTmux(`select-pane -t ${panes[0]}`),{stdio:"ignore"})}catch{}return{leftPane:panes[0],rightPane:panes[1]||panes[0]}}function startTuiTmuxServer(){try{execSync10(tuiTmux(`has-session -t ${TUI_SESSION}`),{stdio:"ignore"})}catch{return freshCreateTuiSession()}try{let panes=execSync10(tuiTmux(`list-panes -t ${TUI_SESSION}:0 -F '#{pane_id}'`),{encoding:"utf-8"}).trim().split(`
2639
2639
  `).filter((id)=>id.length>0);if(panes.length>=2){try{execSync10(tuiTmux(`respawn-pane -k -t ${panes[1]} 'cat'`),{stdio:"ignore"})}catch{}return{leftPane:panes[0],rightPane:panes[1]}}let cols=Number.parseInt(execSync10(tuiTmux(`display-message -t ${TUI_SESSION}:0 -p '#{window_width}'`),{encoding:"utf-8"}).trim(),10)||120;runTuiTmuxCapturing(`split-window -h -t ${TUI_SESSION}:0 -l ${cols-NAV_WIDTH-1}`);let refreshed=execSync10(tuiTmux(`list-panes -t ${TUI_SESSION}:0 -F '#{pane_id}'`),{encoding:"utf-8"}).trim().split(`
@@ -2641,7 +2641,7 @@ ${queryContent}`;let{messages:queryMessages}=state.provider.runQuery({agentId:se
2641
2641
  export `)}`,`exec ${bunPath} ${genieBin}`,""].join(`
2642
2642
  `);writeFileSync20(scriptPath,content,{mode:493});try{execSync10(tuiTmux(`send-keys -t '${leftPane}' '${scriptPath}' Enter`),{stdio:"ignore"})}catch{}}function killTuiSession(){try{execSync10(tuiTmux("kill-server"),{stdio:"ignore"})}catch{}}function listAgentSessions(){try{return execSync10(genieTmuxCmd("list-sessions -F '#{session_name}'"),{encoding:"utf-8"}).trim().split(`
2643
2643
  `).filter(Boolean)}catch{return[]}}function isServeRunning(){let entry2=readServePid();return entry2!==null&&isProcessAlive(entry2.pid)}async function autoStartServe(){if(isStoppingLockActive()){console.log("genie serve is shutting down \u2014 skipping auto-start.");return}if(isServeRunning())return;let bunPath=process.execPath??"bun",genieBin=process.argv[1]??"genie",{spawn:spawnChild}=await import("child_process");spawnChild(bunPath,[genieBin,"serve","--foreground"],{detached:!0,stdio:"ignore",env:{...process.env,GENIE_IS_DAEMON:"1"}}).unref();let deadline=Date.now()+15000;while(Date.now()<deadline)if(await new Promise((resolve12)=>setTimeout(resolve12,500)),isServeRunning()&&isTuiSessionReady())return;if(!isServeRunning())throw Error("genie serve failed to start within 15s. Run `genie serve` manually.")}function isTuiSessionReady(){try{return execSync10(tuiTmux(`has-session -t ${TUI_SESSION}`),{stdio:"ignore"}),!0}catch{return!1}}function ensureTuiSession(workspaceRoot){if(isTuiDisabled()){noticeTuiSkipped("session ensure");return}if(isTuiSessionReady())return;let{leftPane,rightPane}=startTuiTmuxServer();sendTuiLaunchScript(leftPane,rightPane,workspaceRoot)}async function startAgentSync(){try{let{findWorkspace:findWorkspace2,genieHome:genieHome4}=(init_workspace(),__toCommonJS(exports_workspace)),ws=findWorkspace2();if(!ws){let{join:join65}=__require("path"),configPath2=join65(genieHome4(),"config.json");return console.warn(` Agent sync: DISABLED \u2014 no workspace found from cwd or ${configPath2}`),console.warn(" Fix: `cd <workspace> && genie serve restart`, or run `genie init` to bootstrap one"),null}let{syncAgentDirectory:syncAgentDirectory2,watchAgentDirectory:watchAgentDirectory2}=await Promise.resolve().then(() => (init_agent_sync(),exports_agent_sync)),syncResult=await syncAgentDirectory2(ws.root);if(syncResult.registered.length+syncResult.updated.length>0)console.log(` Agent sync: ${syncResult.registered.length} registered, ${syncResult.updated.length} updated (workspace: ${ws.root})`);else console.log(` Agent sync: up to date (workspace: ${ws.root})`);if(syncResult.errors.length>0){console.warn(` Agent sync: ${syncResult.errors.length} error(s) \u2014 these agents were NOT registered:`);for(let e of syncResult.errors)console.warn(` ${e.name}: ${e.error}`)}let watcher2=watchAgentDirectory2(ws.root,{onSync:(name,action)=>{console.log(` [agent-watcher] ${name}: ${action}`)}});if(watcher2)console.log(" Agent watcher started (watching agents/ directory)");else console.warn(" Agent watcher: FAILED to start \u2014 new agents will not be auto-registered");return watcher2}catch(err){let msg=err instanceof Error?err.message:String(err);return console.error(` Agent sync failed: ${msg}`),null}}async function requirePgserveReady(){console.log(" Probing pgserve transport...");try{let{resolvePgserveTransport:resolvePgserveTransport2}=await Promise.resolve().then(() => (init_db(),exports_db)),transport=await resolvePgserveTransport2();if(transport.kind==="unix")console.log(` pgserve ready: unix socket ${transport.socketDir}/.s.PGSQL.${transport.port}`);else console.log(` pgserve ready: tcp ${transport.host}:${transport.port}`);try{let{registerService:registerService2}=await Promise.resolve().then(() => (init_service_registry(),exports_service_registry));registerService2("pgserve-owner",process.pid)}catch{}}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(` pgserve unreachable: ${msg}`),process.env.GENIE_PG_NO_AUTOSTART="1",process.env.GENIE_PG_DISABLE_AUTOSTART="1"}}async function startScheduler(){console.log(" Starting scheduler daemon...");try{let{startDaemon:startDaemon2}=await Promise.resolve().then(() => (init_scheduler_daemon(),exports_scheduler_daemon));handles.schedulerHandle=startDaemon2(),console.log(" Scheduler started (includes event-router + inbox-watcher)");try{let{registerService:registerService2}=await Promise.resolve().then(() => (init_service_registry(),exports_service_registry));registerService2("scheduler",process.pid)}catch{}}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(` Scheduler failed: ${msg}`)}try{let{startDerivedSignalsEngine:startDerivedSignalsEngine2}=await Promise.resolve().then(() => (init_derived_signals(),exports_derived_signals));handles.derivedSignals=await startDerivedSignalsEngine2(),console.log(" Derived-signal rule engine subscribed")}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(` Derived-signal engine failed: ${msg}`)}}function claimServePidOrExit(){let path3=servePidPath();mkdirSync23(genieHome3(),{recursive:!0});let startTime=getProcessStartTime(process.pid)??"unknown",payload=`${process.pid}:${startTime}`;for(let attempt=0;attempt<2;attempt++)try{let fd=openSync5(path3,"wx",420);try{writeSync2(fd,payload)}finally{closeSync5(fd)}return}catch(err){if(err.code!=="EEXIST")throw err;let existing=readServePid();if(existing&&existing.startTime!==null&&isProcessAlive(existing.pid))console.log(`genie serve already running (PID ${existing.pid})`),warnIfHookSocketMissing(),process.exit(0);forceRemoveServePid()}console.error("Could not claim serve.pid after 2 attempts \u2014 another genie serve is racing this one. "+"Wait a moment and retry, or run `genie serve status`."),process.exit(1)}function resolveServeMode(headless){let tuiDisabled=isTuiDisabled();if(tuiDisabled&&!headless)noticeTuiSkipped("serve");return{skipTui:Boolean(headless)||tuiDisabled,mode:headless?"headless":tuiDisabled?"no-tui":"full"}}async function loadBrainStartupConfig(deps){return deps.loadConfig?.()??(await Promise.resolve().then(() => (init_genie_config2(),exports_genie_config))).loadGenieConfigSync()}async function importBrainForStartup(deps){if(deps.importBrain)return deps.importBrain();return import("@khal-os/brain")}async function getBrainStartupPgPort(deps){return deps.getActivePort?.()??(await Promise.resolve().then(() => (init_db(),exports_db))).getActivePort()}function assignBrainHandles(deps,brainHandles){if(deps.setBrainHandles){deps.setBrainHandles(brainHandles);return}handles.brainHandles=brainHandles}function isMissingBrainModule(message){return message.includes("Cannot find")||message.includes("not found")||message.includes("MODULE_NOT_FOUND")}async function startBrainServer(deps,config,log2,warn){let brain=await importBrainForStartup(deps);if(!brain.startEmbeddedBrainServer)return[];let pgPort=await getBrainStartupPgPort(deps);if(!pgPort)return log2(" Brain server: pgserve not available (skipped)"),[];let resolveVaults=deps.resolveVaults??resolveBrainVaults,startVaults=deps.startVaults??startResolvedBrainVaults,resolution=await resolveVaults({brain,config,warn});if(resolution.paths.length===0)return log2(` Brain server: no ${resolution.source} brain vaults found (skipped)`),[];log2(` Starting brain server (${resolution.paths.length} ${resolution.source} vault(s))...`);let brainHandles=await startVaults(resolution,brain,pgPort,{warn,log:log2});if(assignBrainHandles(deps,brainHandles),brainHandles.length===0)log2(" Brain server: no vaults started");return brainHandles}async function startBrainServerIfEnabled(deps={}){let config=await loadBrainStartupConfig(deps),brainEmbedded=config.brain?.embedded!==!1,log2=deps.log??console.log,warn=deps.warn??console.warn;if(!brainEmbedded)return log2(" Brain server: skipped (brain.embedded=false \u2014 managed externally)"),[];try{return await startBrainServer(deps,config,log2,warn)}catch(err){let msg=err instanceof Error?err.message:String(err);if(isMissingBrainModule(msg))return[];return warn(` Brain server: failed: ${msg}`),[]}}function logAgentSessionInfo(){let sessions=listAgentSessions();if(sessions.length>0)console.log(` Agent server (-L genie): ${sessions.length} sessions`);else console.log(" Agent server (-L genie): no sessions yet (created on first spawn)")}function startTuiSessionIfEnabled(skipTui){if(skipTui)return;console.log(" Setting up TUI session...");let{leftPane,rightPane}=startTuiTmuxServer(),ws=(()=>{try{let{findWorkspace:findWorkspace2}=(init_workspace(),__toCommonJS(exports_workspace));return findWorkspace2()}catch{return null}})();sendTuiLaunchScript(leftPane,rightPane,ws?.root),console.log(" TUI server ready (session: genie-tui)")}async function startDetectorSchedulerSafely(){try{await Promise.resolve().then(() => (init_built_in(),exports_built_in));let{start:startDetectorScheduler}=await Promise.resolve().then(() => (init_detector_scheduler(),exports_detector_scheduler)),{listDetectors:listDetectors2}=await Promise.resolve().then(() => (init_detectors(),exports_detectors));handles.detectorScheduler=startDetectorScheduler();let registered=listDetectors2().map((d)=>d.id);console.log(` Detector scheduler started (measurement only, 60s \xB1 5s cadence) \u2014 registered: [${registered.join(", ")}]`)}catch(err){let msg=err instanceof Error?err.message:String(err);console.warn(` Detector scheduler: failed \u2014 ${msg}`)}}async function startExecutorReadEndpointSafely(){try{let{startExecutorReadEndpoint:startExecutorReadEndpoint2,getExecutorReadPort:getExecutorReadPort2}=await Promise.resolve().then(() => (init_executor_read(),exports_executor_read));if(await startExecutorReadEndpoint2())console.log(` Executor read endpoint ready on port ${getExecutorReadPort2()}`)}catch(err){let msg=err instanceof Error?err.message:String(err);console.warn(` Executor read endpoint: failed \u2014 ${msg}`)}}async function startOmniApprovalHandlerSafely(){try{let{startOmniApprovalHandler:startOmniApprovalHandler2}=await Promise.resolve().then(() => (init_omni_approval_handler(),exports_omni_approval_handler)),handler=await startOmniApprovalHandler2();if(handler)handles.omniApprovalHandler=handler,console.log(" Omni approval handler started")}catch{}}async function startOmniBridgeSafely(){let{OmniBridge:OmniBridge2}=await Promise.resolve().then(() => (init_omni_bridge(),exports_omni_bridge)),bridge=new OmniBridge2({natsUrl:process.env.GENIE_NATS_URL??"localhost:4222",maxConcurrent:Number(process.env.GENIE_MAX_CONCURRENT??"20"),idleTimeoutMs:Number(process.env.GENIE_IDLE_TIMEOUT_MS??"900000")});try{await bridge.start(),handles.omniBridge=bridge,console.log(" Omni bridge started")}catch(err){let msg=err instanceof Error?err.message:String(err);if(process.env.GENIE_OMNI_REQUIRED==="1")console.error(` Omni bridge: FAILED \u2014 ${msg}`),process.exit(1);console.warn(` Omni bridge: degraded \u2014 ${msg}; set GENIE_OMNI_REQUIRED=1 to make this fatal`)}}async function stopSchedulerHandles(){handles.agentWatcher?.close();let schedulerHandle=handles.schedulerHandle;if(schedulerHandle){schedulerHandle.stop();try{await schedulerHandle.done}catch{}handles.schedulerHandle=null}if(handles.detectorScheduler)handles.detectorScheduler.stop(),handles.detectorScheduler=null;if(handles.derivedSignals)await handles.derivedSignals.stop().catch(()=>{}),handles.derivedSignals=null}async function stopOmniAndBrainServices(){if(handles.omniApprovalHandler)await handles.omniApprovalHandler.stop().catch(()=>{}),handles.omniApprovalHandler=null;if(handles.omniBridge)await handles.omniBridge.stop().catch(()=>{}),handles.omniBridge=null;if(Promise.resolve().then(() => (init_executor_read(),exports_executor_read)).then((m)=>m.stopExecutorReadEndpoint().catch(()=>{})),handles.brainHandles.length>0){for(let handle of handles.brainHandles)await handle.stop().catch(()=>{});handles.brainHandles=[]}}function killRegisteredServices(){try{let{killAllServices:killAllServices2}=(init_service_registry(),__toCommonJS(exports_service_registry));killAllServices2()}catch{}}function removeLegacyPgservePortLockfileIfForcedTcp(){if(process.env.GENIE_PG_FORCE_TCP!=="1")return;try{let lockfilePath=join64(genieHome3(),"pgserve.port");if(existsSync52(lockfilePath))unlinkSync11(lockfilePath)}catch{}}function sigKillRegisteredServices(){try{let{getRegisteredServices:getRegisteredServices2}=(init_service_registry(),__toCommonJS(exports_service_registry));for(let svc of getRegisteredServices2())try{process.kill(svc.pid,"SIGKILL")}catch{}}catch{}}async function startHookSocketSafely(){try{let{startHookSocket:startHookSocket2}=await Promise.resolve().then(() => (init_hook_socket(),exports_hook_socket));handles.hookSocket=await startHookSocket2({strict:process.env.GENIE_STRICT_HOOKS==="1",repoRoot:operatorCwd})}catch(err){if(process.env.GENIE_STRICT_HOOKS==="1"&&err.message.includes("--strict-hooks"))throw err;console.warn(` Hook socket: DISABLED \u2014 ${err.message}`),handles.hookSocket=null}}async function stopHookSocketSafely(){if(!handles.hookSocket)return;try{await handles.hookSocket.stop()}catch{}handles.hookSocket=null}function buildShutdownFn(headless){let shutdownStarted=!1;return{shutdown:async()=>{if(shutdownStarted)return;if(shutdownStarted=!0,console.log(`
2644
- Shutting down genie serve...`),await stopHookSocketSafely(),await stopSchedulerHandles(),await stopOmniAndBrainServices(),killRegisteredServices(),!headless)killTuiSession();removeLegacyPgservePortLockfileIfForcedTcp(),removeServePid(),console.log("genie serve stopped.")},hasStarted:()=>shutdownStarted}}function installGracefulExitHandlers(shutdown2,hasStarted){let gracefulExit=(exitCode)=>{if(hasStarted())return;let forceTimer=setTimeout(()=>{console.error("Graceful shutdown timeout (10s). Force-killing remaining processes."),sigKillRegisteredServices(),removeServePid(),process.exit(1)},1e4);forceTimer.unref(),shutdown2().catch(()=>{}).finally(()=>{clearTimeout(forceTimer),removeServePid(),process.exit(exitCode)})};process.on("SIGTERM",()=>gracefulExit(143)),process.on("SIGINT",()=>gracefulExit(130)),process.on("SIGHUP",()=>gracefulExit(129)),process.on("exit",()=>{removeServePid()}),process.on("uncaughtException",(err)=>{console.error("Uncaught exception in genie serve:",err),gracefulExit(1)})}function writeStartupStatus(status2){let statusPath=process.env.GENIE_SERVE_STARTUP_STATUS;if(!statusPath)return;try{mkdirSync23(dirname22(statusPath),{recursive:!0}),writeFileSync20(statusPath,`${JSON.stringify(status2)}
2644
+ Shutting down genie serve...`),await stopHookSocketSafely(),await stopSchedulerHandles(),await stopOmniAndBrainServices(),killRegisteredServices(),!headless)killTuiSession();removeLegacyPgservePortLockfileIfForcedTcp(),removeServePid(),console.log("genie serve stopped.")},hasStarted:()=>shutdownStarted}}function installGracefulExitHandlers(shutdown2,hasStarted){let gracefulExit=(exitCode)=>{if(hasStarted())return;let forceTimer=setTimeout(()=>{console.error("Graceful shutdown timeout (10s). Force-killing remaining processes."),sigKillRegisteredServices(),removeServePid(),process.exit(1)},1e4);forceTimer.unref(),shutdown2().catch(()=>{}).finally(()=>{clearTimeout(forceTimer),removeServePid(),process.exit(exitCode)})};process.on("SIGTERM",()=>gracefulExit(143)),process.on("SIGINT",()=>gracefulExit(130)),process.on("SIGHUP",()=>gracefulExit(129)),process.on("exit",()=>{removeServePid()}),process.on("uncaughtException",(err)=>{console.error("Uncaught exception in genie serve:",err),gracefulExit(1)})}function writeStartupStatus(status2){let statusPath=process.env.GENIE_SERVE_STARTUP_STATUS;if(!statusPath)return;try{mkdirSync23(dirname23(statusPath),{recursive:!0}),writeFileSync20(statusPath,`${JSON.stringify(status2)}
2645
2645
  `,"utf-8")}catch{}}function readStartupStatus(statusPath){try{let parsed=JSON.parse(readFileSync34(statusPath,"utf-8"));if(typeof parsed.ok!=="boolean")return null;return{ok:parsed.ok,code:typeof parsed.code==="number"?parsed.code:void 0,lines:Array.isArray(parsed.lines)?parsed.lines.filter((line)=>typeof line==="string"):void 0}}catch{return null}}async function waitForStartupStatus(statusPath,childPid,timeoutMs){let deadline=Date.now()+timeoutMs;while(Date.now()<deadline){let status2=readStartupStatus(statusPath);if(status2)return status2;if(!isProcessAlive(childPid))return{ok:!1,code:1};await new Promise((resolve12)=>setTimeout(resolve12,100))}return null}function exitBackgroundStartFailed(){console.error("Error: genie serve exited immediately."),process.exit(1)}function exitStartupStatusFailure(status2){for(let line of status2.lines??[])console.error(line);process.exit(status2.code??1)}function exitStartupStatusMissing(childPid){console.error("Error: genie serve did not report startup precondition status within 16s.");try{process.kill(childPid,"SIGTERM")}catch{}process.exit(1)}async function confirmBackgroundStarted(childPid,startupStatusPath){if(startupStatusPath){let status2=await waitForStartupStatus(startupStatusPath,childPid,16000);if(forceRemovePath(startupStatusPath),status2?.ok===!1)exitStartupStatusFailure(status2);if(status2?.ok!==!0)exitStartupStatusMissing(childPid);if(!isProcessAlive(childPid))exitBackgroundStartFailed();console.log(`genie serve started (PID ${childPid})`);return}if(await new Promise((resolve12)=>setTimeout(resolve12,1000)),!isProcessAlive(childPid))exitBackgroundStartFailed();console.log(`genie serve started (PID ${childPid})`)}async function startForeground(headless,autoFix=!0){operatorCwd=process.cwd(),claimServePidOrExit(),removeLegacyPgservePortLockfileIfForcedTcp();let{skipTui,mode}=resolveServeMode(headless);process.env.GENIE_IS_DAEMON="1";try{let{pinCwdToGeniePackageDir:pinCwdToGeniePackageDir2}=await Promise.resolve().then(() => (init_db(),exports_db));pinCwdToGeniePackageDir2()}catch{}console.log(`genie serve starting (PID ${process.pid}, mode: ${mode})`);let preconditionLines=[],preconditionLog=process.env.GENIE_SERVE_STARTUP_STATUS?(line)=>{preconditionLines.push(line),console.log(line)}:void 0;try{if(!await runStartPreconditions(autoFix,preconditionLog))writeStartupStatus({ok:!1,code:2,lines:preconditionLines}),removeServePid(),process.exit(2)}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`genie serve start preconditions failed: ${msg}`),writeStartupStatus({ok:!1,code:1,lines:[...preconditionLines,`genie serve start preconditions failed: ${msg}`]}),removeServePid(),process.exit(1)}if(writeStartupStatus({ok:!0}),!skipTui)await ensureTmux();if(await requirePgserveReady(),await startBrainServerIfEnabled(),!headless)logAgentSessionInfo();handles.agentWatcher=await startAgentSync(),startTuiSessionIfEnabled(skipTui),await startScheduler(),await startDetectorSchedulerSafely(),await startExecutorReadEndpointSafely(),await startOmniApprovalHandlerSafely(),await startOmniBridgeSafely(),await startHookSocketSafely(),console.log(`
2646
2646
  genie serve is running (${mode}). ${headless?"Send SIGTERM to stop.":"Press Ctrl+C to stop."}`);let{shutdown:shutdown2,hasStarted}=buildShutdownFn(headless);if(installGracefulExitHandlers(shutdown2,hasStarted),handles.schedulerHandle)await handles.schedulerHandle.done;else await new Promise(()=>{});removeServePid()}async function startBackground(headless,autoFix=!0){if(process.env.pm_id)return startForeground(headless,autoFix);let existingEntry=readServePid();if(existingEntry&&isProcessAlive(existingEntry.pid))console.log(`genie serve already running (PID ${existingEntry.pid})`),process.exit(0);if(existingEntry)forceRemoveServePid();let bunPath=process.execPath??"bun",genieBin=process.argv[1]??"genie",startupStatusPath=autoFix?void 0:serveStartupStatusPath(),args=[genieBin,"serve","--foreground"];if(headless)args.push("--headless");if(!autoFix)args.push("--no-fix");let child=spawn4(bunPath,args,{detached:!0,stdio:"ignore",env:{...process.env,GENIE_IS_DAEMON:"1",...startupStatusPath?{GENIE_SERVE_STARTUP_STATUS:startupStatusPath}:{}}});if(child.unref(),child.pid)await confirmBackgroundStarted(child.pid,startupStatusPath);else console.error("Error: failed to spawn genie serve"),process.exit(1)}function forceRemoveServePid(){forceRemovePath(servePidPath())}function forceRemovePath(path3){try{unlinkSync11(path3)}catch{}}async function stopServe(){let entry2=readServePid();if(!entry2){console.log("genie serve is not running (no PID file).");return}writeStoppingLockSync();try{let pid=entry2.pid;if(!isProcessAlive(pid)){console.log(`Stale PID file (PID ${pid} not running). Cleaning up.`),forceRemoveServePid(),killTuiSession();return}console.log(`Stopping genie serve (PID ${pid})...`);try{process.kill(-pid,"SIGTERM")}catch{try{process.kill(pid,"SIGTERM")}catch{}}let deadline=Date.now()+1e4;while(Date.now()<deadline&&isProcessAlive(pid))await new Promise((resolve12)=>setTimeout(resolve12,250));if(isProcessAlive(pid)){console.log("Did not stop within 10s. Sending SIGKILL.");try{process.kill(-pid,"SIGKILL")}catch{try{process.kill(pid,"SIGKILL")}catch{}}}killTuiSession(),forceRemoveServePid(),console.log("genie serve stopped.")}finally{clearStoppingLock()}}async function printPgserveHealth(){try{let{isAvailable:isAvailable2,getActivePort:getActivePort2,isSocketMode:isSocketMode2,resolvePgserveSocketDir:resolvePgserveSocketDir2}=await Promise.resolve().then(() => (init_db(),exports_db)),dbOk=await isAvailable2(),where=isSocketMode2()?`socket ${resolvePgserveSocketDir2()}`:`port ${getActivePort2()}`;console.log(` pgserve: ${dbOk?`healthy (${where})`:"unreachable"}`)}catch{console.log(" pgserve: unavailable")}}function hookSocketPath(){return process.env.GENIE_HOOK_SOCK??join64(genieHome3(),"hook.sock")}function warnIfHookSocketMissing(){let sock=hookSocketPath();if(existsSync52(sock))return;let lines=[` WARNING: hook UDS not found at ${sock}.`," Daemon-mode hook dispatch is INACTIVE \u2014 every hook will fall back"," to the legacy F1 bun-fork path (hookify-perf-foundation gains lost)."," Remediation: `genie serve stop && genie serve start` to refresh the"," daemon and re-create the socket."];console.warn(lines.join(`
2647
2647
  `))}function printHookSocketStatus(){let sock=hookSocketPath();if(existsSync52(sock))console.log(` hook UDS: listening at ${sock}`);else console.log(` hook UDS: MISSING at ${sock} (F1 fallback active \u2014 see #1490)`)}function resolveBrainPortFromWorkspace(brain){try{let{findWorkspace:findWorkspace2}=(init_workspace(),__toCommonJS(exports_workspace)),ws=findWorkspace2();if(ws?.root&&brain.readServerInfo){let info=brain.readServerInfo(join64(ws.root,"brain"));if(info?.port)return info.port}}catch{}return null}async function probeBrainHealth(brainPort){try{let resp=await fetch(`http://127.0.0.1:${brainPort}/healthz`);console.log(resp.ok?` brain: running (port ${brainPort})`:` brain: unhealthy (port ${brainPort}, status ${resp.status})`)}catch{console.log(` brain: stopped (port ${brainPort} unreachable)`)}}async function printBrainStatus(){try{let brain=await import("@khal-os/brain");if(handles.brainHandles.length>0){for(let handle of handles.brainHandles)await probeBrainHealth(handle.port);return}let brainPort=resolveBrainPortFromWorkspace(brain);if(brainPort)await probeBrainHealth(brainPort);else console.log(" brain: stopped")}catch{console.log(" brain: not installed")}}async function printPgserveStatus(){await printPgserveHealth(),printHookSocketStatus(),await printBrainStatus()}function printTmuxStatus(){let agentRunning=isGenieTmuxRunning(),sessions=agentRunning?listAgentSessions():[];if(console.log(` tmux -L genie: ${agentRunning?`running (${sessions.length} sessions)`:"stopped"}`),sessions.length>0)console.log(` ${sessions.join(", ")}`);let tuiReady=isTuiSessionReady();console.log(` tmux -L genie-tui: ${tuiReady?"running":"stopped"}`)}async function printDaemonStatus(serveRunning){try{let schedulerPidPath=join64(genieHome3(),"scheduler.pid");if(existsSync52(schedulerPidPath)){let sPid=Number.parseInt(readFileSync34(schedulerPidPath,"utf-8").trim(),10),sAlive=!Number.isNaN(sPid)&&isProcessAlive(sPid);console.log(` scheduler: ${sAlive?`running (PID ${sPid})`:"stopped"}`)}else if(serveRunning)console.log(" scheduler: integrated (in-process)");else console.log(" scheduler: stopped")}catch{console.log(" scheduler: unknown")}try{let{getInboxPollIntervalMs:getInboxPollIntervalMs2}=await Promise.resolve().then(() => (init_inbox_watcher(),exports_inbox_watcher)),pollMs=getInboxPollIntervalMs2();if(pollMs===0)console.log(" inbox: disabled");else console.log(` inbox: ${serveRunning?"watching":"stopped"} (poll ${pollMs/1000}s)`)}catch{console.log(" inbox: unavailable")}}async function printBridgeStatus(){try{let{getBridgeStatus:getBridgeStatus2}=await Promise.resolve().then(() => (init_bridge_status(),exports_bridge_status)),res=await getBridgeStatus2();if(res.state==="running"&&res.pong){let uptimeSec=Math.round(res.pong.uptimeMs/1000),latency=res.latencyMs??0;console.log(` omni-bridge: running (pid ${res.pong.pid}, uptime ${uptimeSec}s, ping ${latency}ms)`)}else if(res.state==="stale")console.log(` omni-bridge: stale \u2014 ${res.detail}`);else console.log(" omni-bridge: stopped")}catch{console.log(" omni-bridge: unavailable")}}async function statusServe(){let entry2=readServePid(),running2=entry2!==null&&isProcessAlive(entry2.pid);if(console.log(`
@@ -2964,7 +2964,7 @@ Genie Serve`),console.log("\u2500".repeat(50)),console.log(` Status: ${runn
2964
2964
  SELECT * FROM assignments
2965
2965
  WHERE executor_id = ${executorId}
2966
2966
  ORDER BY started_at ASC
2967
- `).map(rowToAssignment)}async function getAssignment(id){let rows=await(await getConnection())`SELECT * FROM assignments WHERE id = ${id}`;return rows.length>0?rowToAssignment(rows[0]):null}var init_assignment_registry=__esm(()=>{init_db()});var exports_state={};__export(exports_state,{statusCommand:()=>statusCommand,resolveWishPath:()=>resolveWishPath,resetAction:()=>resetAction,registerStateCommands:()=>registerStateCommands,printTerminalWishLifecycleStatus:()=>printTerminalWishLifecycleStatus,parseWishLifecycleStatus:()=>parseWishLifecycleStatus,parseRef:()=>parseRef,getTerminalWishLifecycleStatus:()=>getTerminalWishLifecycleStatus,ensureWorkPushed:()=>ensureWorkPushed,doneCommand:()=>doneCommand,detectWaveCompletion:()=>detectWaveCompletion,archiveWishNamedAgents:()=>archiveWishNamedAgents});import{execSync as execSync13}from"child_process";import{existsSync as existsSync61}from"fs";import{readFile as readFile12}from"fs/promises";import{dirname as dirname26,join as join73}from"path";async function loadExecutorInfo(){let[registryMod,executorMod,assignmentMod]=await Promise.all([Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),Promise.resolve().then(() => (init_assignment_registry(),exports_assignment_registry))]);return{registry:registryMod,executorRegistry:executorMod,assignmentRegistry:assignmentMod}}function normalizeGitPath2(path3){if(process.platform!=="darwin")return path3;if(!path3.startsWith("/private/"))return path3;let logicalPath=path3.slice(8);return existsSync61(logicalPath)?logicalPath:path3}function resolveWishPath(slug,cwd){let base=cwd??process.cwd(),cwdPath=join73(base,".genie","wishes",slug,"WISH.md");if(existsSync61(cwdPath))return cwdPath;try{let commonDir=execSync13("git rev-parse --path-format=absolute --git-common-dir",{encoding:"utf-8",cwd:base,stdio:["pipe","pipe","pipe"]}).trim(),repoRoot=normalizeGitPath2(dirname26(commonDir));if(repoRoot!==base){let repoPath=join73(repoRoot,".genie","wishes",slug,"WISH.md");if(existsSync61(repoPath))return repoPath}}catch{}return findWishInWorkspaceRepos(slug)}function findWishInWorkspaceRepos(slug){try{let home=process.env.GENIE_HOME??join73(__require("os").homedir(),".genie"),configPath2=join73(home,"config.json");if(!existsSync61(configPath2))return null;let raw=__require("fs").readFileSync(configPath2,"utf-8"),config=JSON.parse(raw),wsRoot=typeof config.workspaceRoot==="string"?config.workspaceRoot:null;if(!wsRoot)return null;let candidateRoots=collectRepoCandidates(wsRoot);for(let root of candidateRoots){let candidate=join73(root,".genie","wishes",slug,"WISH.md");if(existsSync61(candidate))return candidate}}catch{}return null}function collectRepoCandidates(workspaceRoot){let fs2=__require("fs"),candidates=[workspaceRoot],reposDir=join73(workspaceRoot,"repos");try{if(fs2.existsSync(reposDir)){for(let entry2 of fs2.readdirSync(reposDir,{withFileTypes:!0}))if(entry2.isDirectory())candidates.push(join73(reposDir,entry2.name))}}catch{}return candidates}function parseRef(ref){let hashIdx=ref.indexOf("#");if(hashIdx===-1)throw Error(`Invalid reference "${ref}". Expected format: <slug>#<group>`);let slug=ref.slice(0,hashIdx),group=ref.slice(hashIdx+1);if(!slug||!group)throw Error(`Invalid reference "${ref}". Both slug and group are required.`);return{slug,group}}async function detectWaveCompletion(slug,groupName,cwd){let wishPath=resolveWishPath(slug,cwd);if(!wishPath)return null;let content=await readFile12(wishPath,"utf-8"),targetWave=parseExecutionStrategy(content).find((w)=>w.groups.some((g)=>g.group===groupName));if(!targetWave)return null;let state=await getState(slug,cwd);if(!state)return null;let waveGroupNames=targetWave.groups.map((g)=>g.group);if(!waveGroupNames.every((g)=>state.groups[g]?.status==="done"))return null;return{waveName:targetWave.name,waveGroups:waveGroupNames}}async function ensureWorkPushed(slug,group){try{if(execSync13("git status --porcelain",{encoding:"utf-8"}).trim())console.log(" Committing dirty working tree..."),execSync13("git add -A",{encoding:"utf-8"}),execSync13(`git commit -m "wip: ${slug}#${group}"`,{encoding:"utf-8"}),console.log(` Committed as "wip: ${slug}#${group}"`)}catch{}try{if(execSync13("git log @{u}..HEAD --oneline",{encoding:"utf-8"}).trim())console.log(" Pushing unpushed commits..."),execSync13("git push",{encoding:"utf-8",timeout:30000}),console.log(" Push complete.")}catch{try{let branch=execSync13("git rev-parse --abbrev-ref HEAD",{encoding:"utf-8"}).trim();if(branch&&branch!=="HEAD")execSync13(`git push -u origin ${branch}`,{encoding:"utf-8",timeout:30000}),console.log(" Push complete (set upstream).")}catch{console.log(" \u26A0\uFE0F Push failed \u2014 manual push may be needed.")}}}async function autoCleanupTeam(){let teamName=process.env.GENIE_TEAM;if(!teamName)return;try{let teamManager=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),config=await teamManager.getTeam(teamName);if(!config)return;if(config.status==="done")return;console.log(` \uD83E\uDDF9 Auto-cleaning team "${teamName}"...`),await teamManager.setTeamStatus(teamName,"done"),await teamManager.killTeamMembers(teamName),console.log(` \u2705 Team "${teamName}" marked done, members killed.`)}catch{console.log(` \u26A0\uFE0F Auto-cleanup skipped \u2014 run \`genie team done ${teamName}\` manually.`)}}async function archiveWishNamedAgents(slug){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
2967
+ `).map(rowToAssignment)}async function getAssignment(id){let rows=await(await getConnection())`SELECT * FROM assignments WHERE id = ${id}`;return rows.length>0?rowToAssignment(rows[0]):null}var init_assignment_registry=__esm(()=>{init_db()});var exports_state={};__export(exports_state,{statusCommand:()=>statusCommand,resolveWishPath:()=>resolveWishPath,resetAction:()=>resetAction,registerStateCommands:()=>registerStateCommands,printTerminalWishLifecycleStatus:()=>printTerminalWishLifecycleStatus,parseWishLifecycleStatus:()=>parseWishLifecycleStatus,parseRef:()=>parseRef,getTerminalWishLifecycleStatus:()=>getTerminalWishLifecycleStatus,ensureWorkPushed:()=>ensureWorkPushed,doneCommand:()=>doneCommand,detectWaveCompletion:()=>detectWaveCompletion,archiveWishNamedAgents:()=>archiveWishNamedAgents});import{execSync as execSync13}from"child_process";import{existsSync as existsSync61}from"fs";import{readFile as readFile12}from"fs/promises";import{dirname as dirname27,join as join73}from"path";async function loadExecutorInfo(){let[registryMod,executorMod,assignmentMod]=await Promise.all([Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),Promise.resolve().then(() => (init_assignment_registry(),exports_assignment_registry))]);return{registry:registryMod,executorRegistry:executorMod,assignmentRegistry:assignmentMod}}function normalizeGitPath2(path3){if(process.platform!=="darwin")return path3;if(!path3.startsWith("/private/"))return path3;let logicalPath=path3.slice(8);return existsSync61(logicalPath)?logicalPath:path3}function resolveWishPath(slug,cwd){let base=cwd??process.cwd(),cwdPath=join73(base,".genie","wishes",slug,"WISH.md");if(existsSync61(cwdPath))return cwdPath;try{let commonDir=execSync13("git rev-parse --path-format=absolute --git-common-dir",{encoding:"utf-8",cwd:base,stdio:["pipe","pipe","pipe"]}).trim(),repoRoot=normalizeGitPath2(dirname27(commonDir));if(repoRoot!==base){let repoPath=join73(repoRoot,".genie","wishes",slug,"WISH.md");if(existsSync61(repoPath))return repoPath}}catch{}return findWishInWorkspaceRepos(slug)}function findWishInWorkspaceRepos(slug){try{let home=process.env.GENIE_HOME??join73(__require("os").homedir(),".genie"),configPath2=join73(home,"config.json");if(!existsSync61(configPath2))return null;let raw=__require("fs").readFileSync(configPath2,"utf-8"),config=JSON.parse(raw),wsRoot=typeof config.workspaceRoot==="string"?config.workspaceRoot:null;if(!wsRoot)return null;let candidateRoots=collectRepoCandidates(wsRoot);for(let root of candidateRoots){let candidate=join73(root,".genie","wishes",slug,"WISH.md");if(existsSync61(candidate))return candidate}}catch{}return null}function collectRepoCandidates(workspaceRoot){let fs2=__require("fs"),candidates=[workspaceRoot],reposDir=join73(workspaceRoot,"repos");try{if(fs2.existsSync(reposDir)){for(let entry2 of fs2.readdirSync(reposDir,{withFileTypes:!0}))if(entry2.isDirectory())candidates.push(join73(reposDir,entry2.name))}}catch{}return candidates}function parseRef(ref){let hashIdx=ref.indexOf("#");if(hashIdx===-1)throw Error(`Invalid reference "${ref}". Expected format: <slug>#<group>`);let slug=ref.slice(0,hashIdx),group=ref.slice(hashIdx+1);if(!slug||!group)throw Error(`Invalid reference "${ref}". Both slug and group are required.`);return{slug,group}}async function detectWaveCompletion(slug,groupName,cwd){let wishPath=resolveWishPath(slug,cwd);if(!wishPath)return null;let content=await readFile12(wishPath,"utf-8"),targetWave=parseExecutionStrategy(content).find((w)=>w.groups.some((g)=>g.group===groupName));if(!targetWave)return null;let state=await getState(slug,cwd);if(!state)return null;let waveGroupNames=targetWave.groups.map((g)=>g.group);if(!waveGroupNames.every((g)=>state.groups[g]?.status==="done"))return null;return{waveName:targetWave.name,waveGroups:waveGroupNames}}async function ensureWorkPushed(slug,group){try{if(execSync13("git status --porcelain",{encoding:"utf-8"}).trim())console.log(" Committing dirty working tree..."),execSync13("git add -A",{encoding:"utf-8"}),execSync13(`git commit -m "wip: ${slug}#${group}"`,{encoding:"utf-8"}),console.log(` Committed as "wip: ${slug}#${group}"`)}catch{}try{if(execSync13("git log @{u}..HEAD --oneline",{encoding:"utf-8"}).trim())console.log(" Pushing unpushed commits..."),execSync13("git push",{encoding:"utf-8",timeout:30000}),console.log(" Push complete.")}catch{try{let branch=execSync13("git rev-parse --abbrev-ref HEAD",{encoding:"utf-8"}).trim();if(branch&&branch!=="HEAD")execSync13(`git push -u origin ${branch}`,{encoding:"utf-8",timeout:30000}),console.log(" Push complete (set upstream).")}catch{console.log(" \u26A0\uFE0F Push failed \u2014 manual push may be needed.")}}}async function autoCleanupTeam(){let teamName=process.env.GENIE_TEAM;if(!teamName)return;try{let teamManager=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),config=await teamManager.getTeam(teamName);if(!config)return;if(config.status==="done")return;console.log(` \uD83E\uDDF9 Auto-cleaning team "${teamName}"...`),await teamManager.setTeamStatus(teamName,"done"),await teamManager.killTeamMembers(teamName),console.log(` \u2705 Team "${teamName}" marked done, members killed.`)}catch{console.log(` \u26A0\uFE0F Auto-cleanup skipped \u2014 run \`genie team done ${teamName}\` manually.`)}}async function archiveWishNamedAgents(slug){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
2968
2968
  UPDATE agents
2969
2969
  SET auto_resume = false,
2970
2970
  state = 'archived',
@@ -2982,14 +2982,14 @@ Team will be auto-cleaned. Run \`genie team done\` to confirm or override.`:`${w
2982
2982
  Run /review or advance to next wave.`,result2=await protocolRouter.sendMessage(repoPath,"cli",leader,message);if(result2&&typeof result2==="object"&&"delivered"in result2&&!result2.delivered)console.warn(` \u26A0\uFE0F Wave-complete notification to ${leader} may not have been delivered.`);else console.log(` Notified ${leader} of wave completion.`);if(spawner&&spawner!==leader&&spawner!=="cli")await protocolRouter.sendMessage(repoPath,"cli",spawner,message).catch(()=>{}),console.log(` Notified spawner (${spawner}) of wave completion.`)}catch{console.warn(" \u26A0\uFE0F Could not notify leader (messaging unavailable).")}}async function doneCommand(ref,report2){if(!report2?.trim())throw Error("doneCommand: report is required \u2014 full group handoff (what shipped, verified, left, surprises). Not a one-liner.");try{let{slug,group}=parseRef(ref),result2=await completeGroup(slug,group);if(console.log(`\u2705 Group "${group}" marked as done in wish "${slug}"`),console.log("--- Handoff ---"),console.log(report2.trimEnd()),console.log("--- End handoff ---"),result2.completedAt)console.log(` Completed at: ${formatTimestamp(result2.completedAt)}`);let state=await getState(slug);if(state){let nowReady=Object.entries(state.groups).filter(([,g])=>g.status==="ready"&&g.dependsOn.includes(group)).map(([name])=>name);if(nowReady.length>0)console.log(` Unblocked: ${nowReady.join(", ")}`)}await ensureWorkPushed(slug,group);let wishComplete=await isWishComplete(slug),waveResult=await detectWaveCompletion(slug,group);if(waveResult)await notifyWaveCompletion(waveResult,wishComplete,report2);if(wishComplete)console.log(" \uD83C\uDF89 Wish fully complete \u2014 all groups done."),await autoCleanupTeam(),await archiveWishNamedAgents(slug);autoKillPane()}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}async function autoInitWishState(slug){let wishPath=resolveWishPath(slug);if(!wishPath)console.error(`\u274C No state found for wish "${slug}" and no WISH.md found in cwd or repo root`),console.error(` Create it first: genie wish <agent> ${slug}`),process.exit(1);let content=await readFile12(wishPath,"utf-8"),groups=parseWishGroups(content);if(groups.length===0)console.error(`\u274C No execution groups found in ${wishPath}`),process.exit(1);let state=await createState(slug,groups);return console.log(`\uD83D\uDCDD Auto-initialized state for wish "${slug}" (${groups.length} groups)`),state}function parseWishLifecycleStatus(content){let patterns2=[/^\|\s*\*\*Status\*\*\s*\|\s*([^|]+?)\s*\|/im,/^\*\*Status:\*\*\s*([A-Za-z][A-Za-z_-]*)/im,/^Status:\s*([A-Za-z][A-Za-z_-]*)/im];for(let pattern of patterns2){let token=content.match(pattern)?.[1]?.trim().match(/^[A-Za-z][A-Za-z_-]*/)?.[0];if(token)return token.toUpperCase()}return null}async function getTerminalWishLifecycleStatus(slug){let wishPath=resolveWishPath(slug);if(!wishPath)return null;let content=await readFile12(wishPath,"utf-8"),status2=parseWishLifecycleStatus(content);if(!status2||!TERMINAL_WISH_STATUSES.has(status2.toLowerCase()))return null;return{status:status2,wishPath}}function printTerminalWishLifecycleStatus(slug,terminal){console.log(`
2983
2983
  Wish: ${slug}`),console.log("\u2500".repeat(60)),console.log(` Status: ${terminal.status}`),console.log(` Source: ${terminal.wishPath}`),console.log(""),console.log(" No active execution state initialized for terminal wish status."),console.log("")}async function printWishExecutors(slug){try{let{registry:registry3,executorRegistry,assignmentRegistry}=await loadExecutorInfo(),agents=await registry3.listAgents({team:process.env.GENIE_TEAM}),executorInfoLines=[];for(let agent of agents){if(!agent.currentExecutorId)continue;let executor=await executorRegistry.getExecutor(agent.currentExecutorId);if(!executor||executor.state==="terminated"||executor.state==="done")continue;let assignment=await assignmentRegistry.getActiveAssignment(executor.id);if(assignment?.wishSlug!==slug)continue;let taskLabel=`Group ${assignment.groupNumber??"?"}`,name=agent.customName??agent.role??agent.id.slice(0,12);executorInfoLines.push(` Agent: ${padRight(name,16)} | Executor: ${executor.id.slice(0,12)} (${executor.provider}) | State: ${padRight(executor.state,10)} | Task: ${taskLabel}`)}if(executorInfoLines.length>0){console.log(`
2984
2984
  Active Executors:`),console.log("\u2500".repeat(60));for(let line of executorInfoLines)console.log(line)}}catch{}}async function statusCommand(slug){try{let terminal=await getTerminalWishLifecycleStatus(slug);if(terminal){printTerminalWishLifecycleStatus(slug,terminal);return}let state=await getState(slug)??await autoInitWishState(slug);console.log(`
2985
- Wish: ${state.wish}`),console.log("\u2500".repeat(60));let entries=Object.entries(state.groups),maxNameLen=Math.max(...entries.map(([name])=>name.length),5);console.log(` ${padRight("GROUP",maxNameLen)} STATUS ASSIGNEE STARTED COMPLETED`),console.log(` ${"\u2500".repeat(maxNameLen+62)}`);for(let[name,group]of entries){let icon=STATUS_ICONS[group.status]??"\u2753",status2=padRight(`${icon} ${group.status}`,13),assignee=padRight(group.assignee??"-",13),started=padRight(formatTimestamp(group.startedAt)||"-",14),completed=formatTimestamp(group.completedAt)||"-";console.log(` ${padRight(name,maxNameLen)} ${status2} ${assignee} ${started} ${completed}`)}let total=entries.length,done=entries.filter(([,g])=>g.status==="done").length,inProgress=entries.filter(([,g])=>g.status==="in_progress").length,ready=entries.filter(([,g])=>g.status==="ready").length,blocked=entries.filter(([,g])=>g.status==="blocked").length;console.log(""),console.log(` Progress: ${done}/${total} done | ${inProgress} in progress | ${ready} ready | ${blocked} blocked`),await printWishExecutors(slug),console.log("")}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}async function resetAction(ref,options){try{if(ref.includes("#")){let{slug,group}=parseRef(ref),result2=await resetGroup(slug,group);if(console.log(`\uD83D\uDD04 Group "${group}" reset to ready in wish "${slug}"`),result2.status==="ready")console.log(" Status: ready (assignee cleared)");return}await resetWishCommand(ref,options?.yes??!1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}function registerStateCommands(_program){}async function confirmWipe(slug,existing,confirmed){let groupCount=Object.keys(existing.groups).length,inProgress=Object.values(existing.groups).filter((g)=>g.status==="in_progress").length,summary=`Wipe all state for "${slug}" (${groupCount} groups, ${inProgress} in-progress)?`;if(!isInteractive()){if(confirmed)return!0;console.error(`\u274C ${summary}`),console.error(" Refusing to wipe in non-interactive mode. Pass --yes to confirm."),process.exit(2)}let{confirm:confirm3}=await Promise.resolve().then(() => (init_esm14(),exports_esm));return confirm3({message:summary,default:!1})}function printResetState(state){console.log(""),console.log(`Wish: ${state.wish}`),console.log("\u2500".repeat(60));for(let[name,group]of Object.entries(state.groups)){let icon=STATUS_ICONS[group.status]??"\u2753";console.log(` ${name} ${icon} ${group.status}`)}}async function resetWishCommand(slug,confirmed){let wishPath=resolveWishPath(slug);if(!wishPath)throw Error(`No WISH.md found for "${slug}" \u2014 searched cwd and repo root`);let content=await readFile12(wishPath,"utf-8"),groups=parseWishGroups(content);if(groups.length===0)throw Error(`No execution groups found in ${wishPath}`);let existing=await getState(slug);if(existing){if(!await confirmWipe(slug,existing,confirmed)){console.log("Aborted.");return}console.log(`\uD83D\uDDD1\uFE0F Replacing existing state for wish "${slug}"`)}else console.log(`\u2139\uFE0F No existing state for wish "${slug}" \u2014 creating fresh`);let state=await createState(slug,groups);console.log(`\uD83D\uDCDD Recreated state from ${wishPath} (${groups.length} groups)`),printResetState(state)}var STATUS_ICONS,TERMINAL_WISH_STATUSES;var init_state=__esm(()=>{init_interactivity();init_term_format();init_wish_state();init_dispatch();STATUS_ICONS={blocked:"\uD83D\uDD12",ready:"\uD83D\uDFE2",in_progress:"\uD83D\uDD04",done:"\u2705"};TERMINAL_WISH_STATUSES=new Set(["shipped","done","complete","completed","archived"])});var exports_team={};__export(exports_team,{registerTeamNamespace:()=>registerTeamNamespace,handleTeamRepair:()=>handleTeamRepair,handleTeamCreate:()=>handleTeamCreate});import{existsSync as existsSync62,mkdirSync as mkdirSync29,renameSync as renameSync11,statSync as statSync15}from"fs";import{copyFile as copyFile3,cp,mkdir as mkdir8}from"fs/promises";import{homedir as homedir48}from"os";import{join as join74,resolve as resolve15}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)").addHelpText("after",`
2985
+ Wish: ${state.wish}`),console.log("\u2500".repeat(60));let entries=Object.entries(state.groups),maxNameLen=Math.max(...entries.map(([name])=>name.length),5);console.log(` ${padRight("GROUP",maxNameLen)} STATUS ASSIGNEE STARTED COMPLETED`),console.log(` ${"\u2500".repeat(maxNameLen+62)}`);for(let[name,group]of entries){let icon=STATUS_ICONS[group.status]??"\u2753",status2=padRight(`${icon} ${group.status}`,13),assignee=padRight(group.assignee??"-",13),started=padRight(formatTimestamp(group.startedAt)||"-",14),completed=formatTimestamp(group.completedAt)||"-";console.log(` ${padRight(name,maxNameLen)} ${status2} ${assignee} ${started} ${completed}`)}let total=entries.length,done=entries.filter(([,g])=>g.status==="done").length,inProgress=entries.filter(([,g])=>g.status==="in_progress").length,ready=entries.filter(([,g])=>g.status==="ready").length,blocked=entries.filter(([,g])=>g.status==="blocked").length;console.log(""),console.log(` Progress: ${done}/${total} done | ${inProgress} in progress | ${ready} ready | ${blocked} blocked`),await printWishExecutors(slug),console.log("")}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}async function resetAction(ref,options){try{if(ref.includes("#")){let{slug,group}=parseRef(ref),result2=await resetGroup(slug,group);if(console.log(`\uD83D\uDD04 Group "${group}" reset to ready in wish "${slug}"`),result2.status==="ready")console.log(" Status: ready (assignee cleared)");return}await resetWishCommand(ref,options?.yes??!1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}function registerStateCommands(_program){}async function confirmWipe(slug,existing,confirmed){let groupCount=Object.keys(existing.groups).length,inProgress=Object.values(existing.groups).filter((g)=>g.status==="in_progress").length,summary=`Wipe all state for "${slug}" (${groupCount} groups, ${inProgress} in-progress)?`;if(!isInteractive()){if(confirmed)return!0;console.error(`\u274C ${summary}`),console.error(" Refusing to wipe in non-interactive mode. Pass --yes to confirm."),process.exit(2)}let{confirm:confirm3}=await Promise.resolve().then(() => (init_esm14(),exports_esm));return confirm3({message:summary,default:!1})}function printResetState(state){console.log(""),console.log(`Wish: ${state.wish}`),console.log("\u2500".repeat(60));for(let[name,group]of Object.entries(state.groups)){let icon=STATUS_ICONS[group.status]??"\u2753";console.log(` ${name} ${icon} ${group.status}`)}}async function resetWishCommand(slug,confirmed){let wishPath=resolveWishPath(slug);if(!wishPath)throw Error(`No WISH.md found for "${slug}" \u2014 searched cwd and repo root`);let content=await readFile12(wishPath,"utf-8"),groups=parseWishGroups(content);if(groups.length===0)throw Error(`No execution groups found in ${wishPath}`);let existing=await getState(slug);if(existing){if(!await confirmWipe(slug,existing,confirmed)){console.log("Aborted.");return}console.log(`\uD83D\uDDD1\uFE0F Replacing existing state for wish "${slug}"`)}else console.log(`\u2139\uFE0F No existing state for wish "${slug}" \u2014 creating fresh`);let state=await createState(slug,groups);console.log(`\uD83D\uDCDD Recreated state from ${wishPath} (${groups.length} groups)`),printResetState(state)}var STATUS_ICONS,TERMINAL_WISH_STATUSES;var init_state=__esm(()=>{init_interactivity();init_term_format();init_wish_state();init_dispatch();STATUS_ICONS={blocked:"\uD83D\uDD12",ready:"\uD83D\uDFE2",in_progress:"\uD83D\uDD04",done:"\u2705"};TERMINAL_WISH_STATUSES=new Set(["shipped","done","complete","completed","archived"])});var exports_team={};__export(exports_team,{registerTeamNamespace:()=>registerTeamNamespace,handleTeamRepair:()=>handleTeamRepair,handleTeamCreate:()=>handleTeamCreate});import{existsSync as existsSync62,mkdirSync as mkdirSync29,renameSync as renameSync12,statSync as statSync15}from"fs";import{copyFile as copyFile2,cp,mkdir as mkdir7}from"fs/promises";import{homedir as homedir48}from"os";import{join as join74,resolve as resolve15}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)").addHelpText("after",`
2986
2986
  Examples:
2987
2987
  genie team create my-feature --repo . # Create team in current repo
2988
2988
  genie team create my-feature --repo . --wish my-feature-slug # Create team with a wish
2989
2989
  genie team create hotfix --repo . --branch main # Create from main branch`).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)}}),team.command("repair <name>").description("Archive an orphaned team-config dir to ~/.claude/teams/_archive/").option("--dry-run","Show what would be archived without doing it").addHelpText("after",`
2990
2990
  This command resolves the doctor's "team_config_orphans" warning by moving
2991
2991
  ~/.claude/teams/<name>/ (which has no corresponding PG team row) into the
2992
- _archive/ subdirectory. Inboxes are preserved on disk; nothing is deleted.`).action(async(name,options)=>{try{await handleTeamRepair(name,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=resolve15(options.repo);if(options.wish){let wishPath=join74(resolvedRepo,".genie","wishes",options.wish,"WISH.md");if(!existsSync62(wishPath)){let cwdWishDir=join74(process.cwd(),".genie","wishes",options.wish),cwdWishPath=join74(cwdWishDir,"WISH.md");if(existsSync62(cwdWishPath)){let destDir=join74(resolvedRepo,".genie","wishes",options.wish);await mkdir8(destDir,{recursive:!0}),await cp(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=resolve15(repoPath),tmuxSession=sessionOverride??config.tmuxSessionName??await findSessionByRepo2(resolvedRepo)??await resolveRepoSession2(resolvedRepo);config.tmuxSessionName=tmuxSession,await updateTeamConfig(config.name,config);let leaderAgent=config.name;config.spawner=process.env.GENIE_AGENT_NAME||"cli",await updateTeamConfig(config.name,config);let sourceWishPath=join74(resolvedRepo,".genie","wishes",slug,"WISH.md");if(!existsSync62(sourceWishPath))console.error(`Error: Wish not found at ${sourceWishPath}`),process.exit(1);let destWishDir=join74(config.worktreePath,".genie","wishes",slug);await mkdir8(destWishDir,{recursive:!0});let destWishPath=join74(destWishDir,"WISH.md");await copyFile3(sourceWishPath,destWishPath),console.log(` Wish: copied ${slug}/WISH.md into worktree`);let standardRoles=["engineer","reviewer","qa","fix"];for(let role of standardRoles)await hireAgent(config.name,role);console.log(` Team: hired ${standardRoles.join(", ")}`);let members=standardRoles.filter((r)=>r!=="team-lead").join(", "),spawner=config.spawner||"cli",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). Report completion to: ${spawner} (via genie send --to ${spawner}). Read the wish at .genie/wishes/${slug}/WISH.md and execute the full lifecycle autonomously.`,broadcasts=await getRecentBroadcasts(config.name);if(broadcasts.length>0){let broadcastLines=broadcasts.map((b2)=>`[${b2.sender}] ${b2.text}`).join(`
2992
+ _archive/ subdirectory. Inboxes are preserved on disk; nothing is deleted.`).action(async(name,options)=>{try{await handleTeamRepair(name,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=resolve15(options.repo);if(options.wish){let wishPath=join74(resolvedRepo,".genie","wishes",options.wish,"WISH.md");if(!existsSync62(wishPath)){let cwdWishDir=join74(process.cwd(),".genie","wishes",options.wish),cwdWishPath=join74(cwdWishDir,"WISH.md");if(existsSync62(cwdWishPath)){let destDir=join74(resolvedRepo,".genie","wishes",options.wish);await mkdir7(destDir,{recursive:!0}),await cp(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=resolve15(repoPath),tmuxSession=sessionOverride??config.tmuxSessionName??await findSessionByRepo2(resolvedRepo)??await resolveRepoSession2(resolvedRepo);config.tmuxSessionName=tmuxSession,await updateTeamConfig(config.name,config);let leaderAgent=config.name;config.spawner=process.env.GENIE_AGENT_NAME||"cli",await updateTeamConfig(config.name,config);let sourceWishPath=join74(resolvedRepo,".genie","wishes",slug,"WISH.md");if(!existsSync62(sourceWishPath))console.error(`Error: Wish not found at ${sourceWishPath}`),process.exit(1);let destWishDir=join74(config.worktreePath,".genie","wishes",slug);await mkdir7(destWishDir,{recursive:!0});let destWishPath=join74(destWishDir,"WISH.md");await copyFile2(sourceWishPath,destWishPath),console.log(` Wish: copied ${slug}/WISH.md into worktree`);let standardRoles=["engineer","reviewer","qa","fix"];for(let role of standardRoles)await hireAgent(config.name,role);console.log(` Team: hired ${standardRoles.join(", ")}`);let members=standardRoles.filter((r)=>r!=="team-lead").join(", "),spawner=config.spawner||"cli",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). Report completion to: ${spawner} (via genie send --to ${spawner}). Read the wish at .genie/wishes/${slug}/WISH.md and execute the full lifecycle autonomously.`,broadcasts=await getRecentBroadcasts(config.name);if(broadcasts.length>0){let broadcastLines=broadcasts.map((b2)=>`[${b2.sender}] ${b2.text}`).join(`
2993
2993
  `);kickoffPrompt+=`
2994
2994
 
2995
2995
  Recent team broadcasts for context:
@@ -3004,7 +3004,7 @@ ${broadcastLines}`}await handleWorkerSpawn2("team-lead",{provider:"claude",team:
3004
3004
  ORDER BY m.created_at ASC
3005
3005
  LIMIT 20
3006
3006
  `).map((r)=>({sender:String(r.sender_id),text:String(r.body),timestamp:r.created_at instanceof Date?r.created_at.toISOString():String(r.created_at)}))}catch{return[]}}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 listTeams(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 status2=t.status??"in_progress",dimmed=status2==="archived"?"\x1B[90m":"",reset2=status2==="archived"?"\x1B[0m":"";console.log(` ${dimmed}${t.name} [${status2}]${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 listTeams(!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(`
3007
- ${verb} ${cleaned} window${cleaned===1?"":"s"}.`)}function teamsBaseDir4(){return join74(process.env.CLAUDE_CONFIG_DIR??join74(homedir48(),".claude"),"teams")}async function handleTeamRepair(name,options){let teamsDir=teamsBaseDir4(),orphanPath=join74(teamsDir,name);if(!existsSync62(orphanPath)||!statSync15(orphanPath).isDirectory()){console.log(`No team-config directory at ${orphanPath}. Nothing to repair.`);return}let pgTeam=await getTeam(name).catch(()=>null);if(pgTeam)console.error(`Error: team '${name}' still exists in the registry (status=${pgTeam.status}).`),console.error("Refusing to archive a live team. Use `genie team disband` instead."),process.exit(2);let archiveRoot=join74(teamsDir,"_archive"),ts3=new Date().toISOString().replace(/[:.]/g,"-"),dest=join74(archiveRoot,`${name}-${ts3}`);if(options.dryRun){console.log(`[dry-run] Would archive ${orphanPath} \u2192 ${dest}`);return}mkdirSync29(archiveRoot,{recursive:!0}),renameSync11(orphanPath,dest),console.log(`Archived ${orphanPath} \u2192 ${dest}`)}var init_team=__esm(()=>{init_team_manager()});var exports_wish_sync={};__export(exports_wish_sync,{syncWishes:()=>syncWishes,parseWishStatus:()=>parseWishStatus,listWishes:()=>listWishes,getWish:()=>getWish});import{existsSync as existsSync63,readFileSync as readFileSync42,readdirSync as readdirSync14}from"fs";import{basename as basename11,join as join75}from"path";function parseWishStatus(content){let match=content.match(/\|\s*\*\*Status\*\*\s*\|\s*([^|]+)/i);if(match)return match[1].trim();return"DRAFT"}function scanRepoWishes(repoPath){let wishesDir=join75(repoPath,".genie","wishes");if(!existsSync63(wishesDir))return[];let results=[],namespace=basename11(repoPath);try{let entries=readdirSync14(wishesDir,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;let wishPath=join75(wishesDir,entry2.name,"WISH.md");if(!existsSync63(wishPath))continue;try{let content=readFileSync42(wishPath,"utf-8");results.push({slug:entry2.name,repo:repoPath,namespace,status:parseWishStatus(content),filePath:wishPath})}catch{}}}catch{}return results}function discoverWishes(repoPath){if(repoPath)return scanRepoWishes(repoPath);if(!existsSync63(REPOS_BASE2))return[];let results=[];try{let entries=readdirSync14(REPOS_BASE2,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;results.push(...scanRepoWishes(join75(REPOS_BASE2,entry2.name)))}}catch{}return results}async function syncWishes(repoPath){let wishes=discoverWishes(repoPath);if(wishes.length===0)return 0;let sql=await getConnection();for(let wish of wishes)await sql`
3007
+ ${verb} ${cleaned} window${cleaned===1?"":"s"}.`)}function teamsBaseDir4(){return join74(process.env.CLAUDE_CONFIG_DIR??join74(homedir48(),".claude"),"teams")}async function handleTeamRepair(name,options){let teamsDir=teamsBaseDir4(),orphanPath=join74(teamsDir,name);if(!existsSync62(orphanPath)||!statSync15(orphanPath).isDirectory()){console.log(`No team-config directory at ${orphanPath}. Nothing to repair.`);return}let pgTeam=await getTeam(name).catch(()=>null);if(pgTeam)console.error(`Error: team '${name}' still exists in the registry (status=${pgTeam.status}).`),console.error("Refusing to archive a live team. Use `genie team disband` instead."),process.exit(2);let archiveRoot=join74(teamsDir,"_archive"),ts3=new Date().toISOString().replace(/[:.]/g,"-"),dest=join74(archiveRoot,`${name}-${ts3}`);if(options.dryRun){console.log(`[dry-run] Would archive ${orphanPath} \u2192 ${dest}`);return}mkdirSync29(archiveRoot,{recursive:!0}),renameSync12(orphanPath,dest),console.log(`Archived ${orphanPath} \u2192 ${dest}`)}var init_team=__esm(()=>{init_team_manager()});var exports_wish_sync={};__export(exports_wish_sync,{syncWishes:()=>syncWishes,parseWishStatus:()=>parseWishStatus,listWishes:()=>listWishes,getWish:()=>getWish});import{existsSync as existsSync63,readFileSync as readFileSync42,readdirSync as readdirSync14}from"fs";import{basename as basename11,join as join75}from"path";function parseWishStatus(content){let match=content.match(/\|\s*\*\*Status\*\*\s*\|\s*([^|]+)/i);if(match)return match[1].trim();return"DRAFT"}function scanRepoWishes(repoPath){let wishesDir=join75(repoPath,".genie","wishes");if(!existsSync63(wishesDir))return[];let results=[],namespace=basename11(repoPath);try{let entries=readdirSync14(wishesDir,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;let wishPath=join75(wishesDir,entry2.name,"WISH.md");if(!existsSync63(wishPath))continue;try{let content=readFileSync42(wishPath,"utf-8");results.push({slug:entry2.name,repo:repoPath,namespace,status:parseWishStatus(content),filePath:wishPath})}catch{}}}catch{}return results}function discoverWishes(repoPath){if(repoPath)return scanRepoWishes(repoPath);if(!existsSync63(REPOS_BASE2))return[];let results=[];try{let entries=readdirSync14(REPOS_BASE2,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;results.push(...scanRepoWishes(join75(REPOS_BASE2,entry2.name)))}}catch{}return results}async function syncWishes(repoPath){let wishes=discoverWishes(repoPath);if(wishes.length===0)return 0;let sql=await getConnection();for(let wish of wishes)await sql`
3008
3008
  INSERT INTO wishes (slug, repo, namespace, status, file_path)
3009
3009
  VALUES (${wish.slug}, ${wish.repo}, ${wish.namespace}, ${wish.status}, ${wish.filePath})
3010
3010
  ON CONFLICT (slug, repo) DO UPDATE SET
@@ -3020,7 +3020,7 @@ Return ONLY a bulleted list of relevant excerpts with their source file paths.
3020
3020
  Keep it under 500 words. If nothing is relevant, say "No relevant prior context."`;try{let result2=execSync14(`rlmx ${shellQuote4(rlmxQuery)} --context ${shellQuote4(brainPath)} --output json --max-iterations ${maxIterations} --max-cost ${maxCost}`,{encoding:"utf-8",timeout,env:{...process.env},stdio:["pipe","pipe","pipe"]}),answer=JSON.parse(result2).answer?.trim();if(!answer||answer==="No relevant prior context."||answer.length<20)return"";return`## Prior Context (from brain vault)
3021
3021
 
3022
3022
  ${answer}
3023
- `}catch{return""}}function shellQuote4(s2){return`'${s2.replace(/'/g,"'\\''")}'`}var init_context_enrichment=()=>{};import{execSync as execSync15}from"child_process";import{randomUUID as randomUUID14}from"crypto";import{existsSync as existsSync65}from"fs";import{mkdir as mkdir9,readFile as readFile13,writeFile as writeFile8}from"fs/promises";import{tmpdir as tmpdir3}from"os";import{join as join77}from"path";async function cliSender(){let origin=await detectSenderIdentity();if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(origin))return origin;return origin==="cli"?"cli":`cli:${origin}`}async function writeContextFile(content){let dir=join77(tmpdir3(),"genie-dispatch");await mkdir9(dir,{recursive:!0});let ts3=Date.now().toString(36),rand=Math.random().toString(36).slice(2,8),filePath=join77(dir,`ctx-${ts3}-${rand}.md`);return await writeFile8(filePath,content),filePath}function extractGroup(content,groupName){let pattern=new RegExp(`^### Group ${escapeRegExp(groupName)}:`,"m"),match=content.match(pattern);if(!match||match.index===void 0)return null;let start3=match.index,nextBoundary=content.slice(start3).slice(1).search(/^### Group \d|^---$/m),end=nextBoundary!==-1?start3+1+nextBoundary:content.length;return content.slice(start3,end).trim()}function extractWishContext(content){let execGroupsIdx=content.indexOf("## Execution Groups");if(execGroupsIdx!==-1)return content.slice(0,execGroupsIdx).trim();return content.slice(0,2000).trim()}function validateSlug(slug){if(!SLUG_PATTERN.test(slug))console.error(`\u274C Invalid slug: "${slug}"`),console.error(" Slugs must match [a-zA-Z0-9._-]+ (no slashes, dots-dots, or special characters)"),process.exit(1)}function escapeRegExp(str5){return str5.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function buildContextPrompt(opts){let parts=[`# Dispatch Context (${opts.command})`,"",`**Source file:** \`${opts.filePath}\``,"(Read the full document at the path above for complete context)",""];if(opts.wishContext)parts.push("## Wish Context","",opts.wishContext,"");if(parts.push("## Assigned Section","",opts.sectionContent,""),opts.enrichedContext)parts.push(opts.enrichedContext);if(opts.skill)parts.push("## Initial Command","",`Run \`/${opts.skill}\` to begin.`,"");return parts.join(`
3023
+ `}catch{return""}}function shellQuote4(s2){return`'${s2.replace(/'/g,"'\\''")}'`}var init_context_enrichment=()=>{};import{execSync as execSync15}from"child_process";import{randomUUID as randomUUID14}from"crypto";import{existsSync as existsSync65}from"fs";import{mkdir as mkdir8,readFile as readFile13,writeFile as writeFile8}from"fs/promises";import{tmpdir as tmpdir3}from"os";import{join as join77}from"path";async function cliSender(){let origin=await detectSenderIdentity();if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(origin))return origin;return origin==="cli"?"cli":`cli:${origin}`}async function writeContextFile(content){let dir=join77(tmpdir3(),"genie-dispatch");await mkdir8(dir,{recursive:!0});let ts3=Date.now().toString(36),rand=Math.random().toString(36).slice(2,8),filePath=join77(dir,`ctx-${ts3}-${rand}.md`);return await writeFile8(filePath,content),filePath}function extractGroup(content,groupName){let pattern=new RegExp(`^### Group ${escapeRegExp(groupName)}:`,"m"),match=content.match(pattern);if(!match||match.index===void 0)return null;let start3=match.index,nextBoundary=content.slice(start3).slice(1).search(/^### Group \d|^---$/m),end=nextBoundary!==-1?start3+1+nextBoundary:content.length;return content.slice(start3,end).trim()}function extractWishContext(content){let execGroupsIdx=content.indexOf("## Execution Groups");if(execGroupsIdx!==-1)return content.slice(0,execGroupsIdx).trim();return content.slice(0,2000).trim()}function validateSlug(slug){if(!SLUG_PATTERN.test(slug))console.error(`\u274C Invalid slug: "${slug}"`),console.error(" Slugs must match [a-zA-Z0-9._-]+ (no slashes, dots-dots, or special characters)"),process.exit(1)}function escapeRegExp(str5){return str5.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function buildContextPrompt(opts){let parts=[`# Dispatch Context (${opts.command})`,"",`**Source file:** \`${opts.filePath}\``,"(Read the full document at the path above for complete context)",""];if(opts.wishContext)parts.push("## Wish Context","",opts.wishContext,"");if(parts.push("## Assigned Section","",opts.sectionContent,""),opts.enrichedContext)parts.push(opts.enrichedContext);if(opts.skill)parts.push("## Initial Command","",`Run \`/${opts.skill}\` to begin.`,"");return parts.join(`
3024
3024
  `)}function getGitDiff(){try{let diff=execSync15("git diff HEAD",{encoding:"utf-8",maxBuffer:1048576}),staged=execSync15("git diff --cached",{encoding:"utf-8",maxBuffer:1048576}),combined=[diff,staged].filter(Boolean).join(`
3025
3025
  `);if(combined.length>50000)return`${combined.slice(0,50000)}
3026
3026
 
@@ -3152,7 +3152,7 @@ ${label} <TODO>
3152
3152
  ${actor},
3153
3153
  ${tx.json({agent_id:row2.agent_id,outcome:TRAP_OUTCOME,reason})}
3154
3154
  )
3155
- `,{noop:!1,executorId,outcome:TRAP_OUTCOME,reason}})}catch(err){let msg=err instanceof Error?err.message:String(err);return console.error(`[pane-trap] swallowed error: ${msg}`),result2}}var TRAP_OUTCOME="clean_exit_unverified";var init_pane_trap=__esm(()=>{init_db()});var exports_pane_trap={};__export(exports_pane_trap,{paneTrapAction:()=>paneTrapAction});function normalizeReason(raw){return raw==="shell_exit"?"shell_exit":"pane_died"}async function paneTrapAction(opts){let result2=await trapPaneExit({executorId:opts.executorId,paneId:opts.paneId,reason:normalizeReason(opts.reason)});if(result2.executorId===null)return;if(result2.noop){console.error(`[pane-trap] no-op for ${result2.executorId} (already closed)`);return}console.error(`[pane-trap] terminalized executor=${result2.executorId} outcome=${result2.outcome} reason=${result2.reason}`)}var init_pane_trap2=__esm(()=>{init_pane_trap()});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 as EventEmitter2}from"events";import{Buffer as Buffer2}from"buffer";import{Buffer as Buffer3}from"buffer";import{EventEmitter as EventEmitter22}from"events";import{resolve as resolve20,dirname as dirname32}from"path";import{fileURLToPath as fileURLToPath6}from"url";import{resolve as resolve22,isAbsolute as isAbsolute5,parse as parse2}from"path";import{existsSync as existsSync75}from"fs";import{basename as basename13,join as join90}from"path";import os3 from"os";import path3 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 mkdir13,readFile as readFile18,writeFile as writeFile12}from"fs/promises";import*as path32 from"path";import{readdir as readdir12}from"fs/promises";import{mkdir as mkdir32,writeFile as writeFileNode}from"fs/promises";import{dirname as dirname42}from"path";import{fileURLToPath as fileURLToPath22}from"url";import{fileURLToPath as fileURLToPath32}from"url";import{existsSync as existsSync210,writeFileSync as writeFileSync33}from"fs";import{EventEmitter as EventEmitter4}from"events";import{EventEmitter as EventEmitter5}from"events";import util3 from"util";import{EventEmitter as EventEmitter6}from"events";import{EventEmitter as EventEmitter8}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 EventEmitter7}from"events";import{EventEmitter as EventEmitter9}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 result2=[];if(sides.top)result2.push("top");if(sides.right)result2.push("right");if(sides.bottom)result2.push("bottom");if(sides.left)result2.push("left");return result2.length>0?result2:!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}}function packMeta(intent,slot=0){return(slot&255|(intent&255)<<8)>>>0}function toU8(value){return Math.round(Math.max(0,Math.min(1,Number.isFinite(value)?value:0))*255)}function toByte(value){return Math.round(Math.max(0,Math.min(255,Number.isFinite(value)?value:0)))}function packRGBA8(r,g,b2,a,meta){return new Uint16Array([toByte(r)&255|(meta>>>0&255)<<8,toByte(g)&255|(meta>>>8&255)<<8,toByte(b2)&255|(meta>>>16&255)<<8,toByte(a)&255|(meta>>>24&255)<<8])}function rgbaForAnsi256Index(index){let[r,g,b2]=ansi256IndexToRgb(index);return RGBA.fromInts(r,g,b2)}function normalizeIndexedColorIndex(index){if(!Number.isInteger(index)||index<0||index>255)throw RangeError(`Indexed color must be an integer in the range 0..255, got ${index}`);return index}function ansi256IndexToRgb(index){let normalizedIndex=normalizeIndexedColorIndex(index);if(normalizedIndex<ANSI16_RGB.length)return ANSI16_RGB[normalizedIndex];if(normalizedIndex<232){let cubeIndex=normalizedIndex-16,r=Math.floor(cubeIndex/36),g=Math.floor(cubeIndex/6)%6,b2=cubeIndex%6;return[ANSI_256_CUBE_LEVELS[r],ANSI_256_CUBE_LEVELS[g],ANSI_256_CUBE_LEVELS[b2]]}let value=8+(normalizedIndex-232)*10;return[value,value,value]}class RGBA{buffer;constructor(buffer2){this.buffer=new Uint16Array(4),this.buffer.set(buffer2.subarray(0,4))}static fromArray(array){return new RGBA(array)}static fromValues(r,g,b2,a=1){return new RGBA(packRGBA8(toU8(r),toU8(g),toU8(b2),toU8(a),packMeta(INTENT_RGB)))}static clone(rgba){return new RGBA(rgba.buffer)}static fromInts(r,g,b2,a=255){return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_RGB)))}static fromHex(hex){return hexToRgb2(hex)}static fromIndex(index,snapshot){let normalized=normalizeIndexedColorIndex(index),rgba=snapshot?parseColor(snapshot):rgbaForAnsi256Index(normalized),[r,g,b2,a]=rgba.toInts();return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_INDEXED,normalized)))}static defaultForeground(snapshot){let rgba=snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_FOREGROUND_RGB),[r,g,b2,a]=rgba.toInts();return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_DEFAULT)))}static defaultBackground(snapshot){let rgba=snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_BACKGROUND_RGB),[r,g,b2,a]=rgba.toInts();return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_DEFAULT)))}toInts(){return[this.buffer[0]&255,this.buffer[1]&255,this.buffer[2]&255,this.buffer[3]&255]}get r(){return(this.buffer[0]&255)/255}set r(value){this.buffer[0]=this.buffer[0]&65280|toU8(value)}get g(){return(this.buffer[1]&255)/255}set g(value){this.buffer[1]=this.buffer[1]&65280|toU8(value)}get b(){return(this.buffer[2]&255)/255}set b(value){this.buffer[2]=this.buffer[2]&65280|toU8(value)}get a(){return(this.buffer[3]&255)/255}set a(value){this.buffer[3]=this.buffer[3]&65280|toU8(value)}get meta(){return(this.buffer[0]>>>8|this.buffer[1]>>>8<<8|this.buffer[2]>>>8<<16|this.buffer[3]>>>8<<24)>>>0}get intent(){switch(this.meta>>>8&255){case INTENT_INDEXED:return"indexed";case INTENT_DEFAULT:return"default";default:return"rgb"}}get slot(){return this.meta&255}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.buffer[0]===other.buffer[0]&&this.buffer[1]===other.buffer[1]&&this.buffer[2]===other.buffer[2]&&this.buffer[3]===other.buffer[3]}}function normalizeColorValue(value){if(value==null)return null;return{rgba:parseColor(value)}}function hexToRgb2(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),g=parseInt(hex.substring(2,4),16),b2=parseInt(hex.substring(4,6),16),a=hex.length===8?parseInt(hex.substring(6,8),16):255;return RGBA.fromInts(r,g,b2,a)}function rgbToHex2(rgb){let[r,g,b2,a]=rgb.toInts();return"#"+(a===255?[r,g,b2]:[r,g,b2,a]).map((x)=>x.toString(16).padStart(2,"0")).join("")}function hsvToRgb(h,s2,v){let r=0,g=0,b2=0,i2=Math.floor(h/60)%6,f=h/60-Math.floor(h/60),p=v*(1-s2),q=v*(1-f*s2),t=v*(1-(1-f)*s2);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(color2){if(typeof color2==="string"){let lowerColor=color2.toLowerCase();if(lowerColor==="transparent")return RGBA.fromValues(0,0,0,0);if(CSS_COLOR_NAMES[lowerColor])return hexToRgb2(CSS_COLOR_NAMES[lowerColor]);return hexToRgb2(color2)}return color2}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:color2=[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 colors8=Array.isArray(color2)?color2:[color2];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=colors8[segment.colorIndex]||colors8[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:
3155
+ `,{noop:!1,executorId,outcome:TRAP_OUTCOME,reason}})}catch(err){let msg=err instanceof Error?err.message:String(err);return console.error(`[pane-trap] swallowed error: ${msg}`),result2}}var TRAP_OUTCOME="clean_exit_unverified";var init_pane_trap=__esm(()=>{init_db()});var exports_pane_trap={};__export(exports_pane_trap,{paneTrapAction:()=>paneTrapAction});function normalizeReason(raw){return raw==="shell_exit"?"shell_exit":"pane_died"}async function paneTrapAction(opts){let result2=await trapPaneExit({executorId:opts.executorId,paneId:opts.paneId,reason:normalizeReason(opts.reason)});if(result2.executorId===null)return;if(result2.noop){console.error(`[pane-trap] no-op for ${result2.executorId} (already closed)`);return}console.error(`[pane-trap] terminalized executor=${result2.executorId} outcome=${result2.outcome} reason=${result2.reason}`)}var init_pane_trap2=__esm(()=>{init_pane_trap()});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 as EventEmitter2}from"events";import{Buffer as Buffer2}from"buffer";import{Buffer as Buffer3}from"buffer";import{EventEmitter as EventEmitter22}from"events";import{resolve as resolve20,dirname as dirname33}from"path";import{fileURLToPath as fileURLToPath6}from"url";import{resolve as resolve22,isAbsolute as isAbsolute5,parse as parse2}from"path";import{existsSync as existsSync75}from"fs";import{basename as basename13,join as join90}from"path";import os3 from"os";import path3 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 mkdir12,readFile as readFile18,writeFile as writeFile12}from"fs/promises";import*as path32 from"path";import{readdir as readdir12}from"fs/promises";import{mkdir as mkdir32,writeFile as writeFileNode}from"fs/promises";import{dirname as dirname42}from"path";import{fileURLToPath as fileURLToPath22}from"url";import{fileURLToPath as fileURLToPath32}from"url";import{existsSync as existsSync210,writeFileSync as writeFileSync33}from"fs";import{EventEmitter as EventEmitter4}from"events";import{EventEmitter as EventEmitter5}from"events";import util3 from"util";import{EventEmitter as EventEmitter6}from"events";import{EventEmitter as EventEmitter8}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 EventEmitter7}from"events";import{EventEmitter as EventEmitter9}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 result2=[];if(sides.top)result2.push("top");if(sides.right)result2.push("right");if(sides.bottom)result2.push("bottom");if(sides.left)result2.push("left");return result2.length>0?result2:!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}}function packMeta(intent,slot=0){return(slot&255|(intent&255)<<8)>>>0}function toU8(value){return Math.round(Math.max(0,Math.min(1,Number.isFinite(value)?value:0))*255)}function toByte(value){return Math.round(Math.max(0,Math.min(255,Number.isFinite(value)?value:0)))}function packRGBA8(r,g,b2,a,meta){return new Uint16Array([toByte(r)&255|(meta>>>0&255)<<8,toByte(g)&255|(meta>>>8&255)<<8,toByte(b2)&255|(meta>>>16&255)<<8,toByte(a)&255|(meta>>>24&255)<<8])}function rgbaForAnsi256Index(index){let[r,g,b2]=ansi256IndexToRgb(index);return RGBA.fromInts(r,g,b2)}function normalizeIndexedColorIndex(index){if(!Number.isInteger(index)||index<0||index>255)throw RangeError(`Indexed color must be an integer in the range 0..255, got ${index}`);return index}function ansi256IndexToRgb(index){let normalizedIndex=normalizeIndexedColorIndex(index);if(normalizedIndex<ANSI16_RGB.length)return ANSI16_RGB[normalizedIndex];if(normalizedIndex<232){let cubeIndex=normalizedIndex-16,r=Math.floor(cubeIndex/36),g=Math.floor(cubeIndex/6)%6,b2=cubeIndex%6;return[ANSI_256_CUBE_LEVELS[r],ANSI_256_CUBE_LEVELS[g],ANSI_256_CUBE_LEVELS[b2]]}let value=8+(normalizedIndex-232)*10;return[value,value,value]}class RGBA{buffer;constructor(buffer2){this.buffer=new Uint16Array(4),this.buffer.set(buffer2.subarray(0,4))}static fromArray(array){return new RGBA(array)}static fromValues(r,g,b2,a=1){return new RGBA(packRGBA8(toU8(r),toU8(g),toU8(b2),toU8(a),packMeta(INTENT_RGB)))}static clone(rgba){return new RGBA(rgba.buffer)}static fromInts(r,g,b2,a=255){return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_RGB)))}static fromHex(hex){return hexToRgb2(hex)}static fromIndex(index,snapshot){let normalized=normalizeIndexedColorIndex(index),rgba=snapshot?parseColor(snapshot):rgbaForAnsi256Index(normalized),[r,g,b2,a]=rgba.toInts();return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_INDEXED,normalized)))}static defaultForeground(snapshot){let rgba=snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_FOREGROUND_RGB),[r,g,b2,a]=rgba.toInts();return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_DEFAULT)))}static defaultBackground(snapshot){let rgba=snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_BACKGROUND_RGB),[r,g,b2,a]=rgba.toInts();return new RGBA(packRGBA8(r,g,b2,a,packMeta(INTENT_DEFAULT)))}toInts(){return[this.buffer[0]&255,this.buffer[1]&255,this.buffer[2]&255,this.buffer[3]&255]}get r(){return(this.buffer[0]&255)/255}set r(value){this.buffer[0]=this.buffer[0]&65280|toU8(value)}get g(){return(this.buffer[1]&255)/255}set g(value){this.buffer[1]=this.buffer[1]&65280|toU8(value)}get b(){return(this.buffer[2]&255)/255}set b(value){this.buffer[2]=this.buffer[2]&65280|toU8(value)}get a(){return(this.buffer[3]&255)/255}set a(value){this.buffer[3]=this.buffer[3]&65280|toU8(value)}get meta(){return(this.buffer[0]>>>8|this.buffer[1]>>>8<<8|this.buffer[2]>>>8<<16|this.buffer[3]>>>8<<24)>>>0}get intent(){switch(this.meta>>>8&255){case INTENT_INDEXED:return"indexed";case INTENT_DEFAULT:return"default";default:return"rgb"}}get slot(){return this.meta&255}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.buffer[0]===other.buffer[0]&&this.buffer[1]===other.buffer[1]&&this.buffer[2]===other.buffer[2]&&this.buffer[3]===other.buffer[3]}}function normalizeColorValue(value){if(value==null)return null;return{rgba:parseColor(value)}}function hexToRgb2(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),g=parseInt(hex.substring(2,4),16),b2=parseInt(hex.substring(4,6),16),a=hex.length===8?parseInt(hex.substring(6,8),16):255;return RGBA.fromInts(r,g,b2,a)}function rgbToHex2(rgb){let[r,g,b2,a]=rgb.toInts();return"#"+(a===255?[r,g,b2]:[r,g,b2,a]).map((x)=>x.toString(16).padStart(2,"0")).join("")}function hsvToRgb(h,s2,v){let r=0,g=0,b2=0,i2=Math.floor(h/60)%6,f=h/60-Math.floor(h/60),p=v*(1-s2),q=v*(1-f*s2),t=v*(1-(1-f)*s2);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(color2){if(typeof color2==="string"){let lowerColor=color2.toLowerCase();if(lowerColor==="transparent")return RGBA.fromValues(0,0,0,0);if(CSS_COLOR_NAMES[lowerColor])return hexToRgb2(CSS_COLOR_NAMES[lowerColor]);return hexToRgb2(color2)}return color2}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:color2=[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 colors8=Array.isArray(color2)?color2:[color2];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=colors8[segment.colorIndex]||colors8[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:
3156
3156
  `+treeLines.join(`
3157
3157
  `))}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(`
3158
3158
  `)}}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
@@ -3180,7 +3180,7 @@ No environment variables registered.
3180
3180
  `}else output+=`\x1B[32mDefault:\x1B[0m \x1B[31mRequired\x1B[0m
3181
3181
  `;output+=`
3182
3182
  `}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,start3,endExclusive){if(start3>=endExclusive)return null;let value=0,sawDigit=!1;for(let index=start3;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 parseKittyFirstFieldCodepoint(sequence,start3,endExclusive){if(start3>=endExclusive)return null;let firstColon=-1;for(let index=start3;index<endExclusive;index+=1)if(sequence[index]===58){firstColon=index;break}if(firstColon===-1)return null;let codepoint=parsePositiveDecimalPrefix(sequence,start3,firstColon);if(codepoint===null)return null;for(let index=firstColon+1;index<endExclusive;index+=1){let byte=sequence[index];if(byte!==58&&!isAsciiDigit(byte))return null}return codepoint}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 canStillBeStartupCursorCpr(state){return state.semicolons===1}function canStillBeStartupCursorCprPrefix(state){return state.segments===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.startupCursorCprActive&&canStillBeStartupCursorCpr(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.startupCursorCprActive&&state.hasDigit&&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 classifyParametricCsiProtocol(state,finalByte){if(finalByte===82&&state.semicolons===1&&state.segments===1&&state.hasDigit)return"cpr";return"csi"}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;if(byte===110)return state.hasDigit;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_MS2),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,startupCursorCprActive:options.protocolContext?.startupCursorCprActive??!1}}get bufferCapacity(){return this.pending.capacity}updateProtocolContext(patch){this.ensureAlive(),this.protocolContext={...this.protocolContext,...patch},this.reconcileDeferredStateWithProtocolContext(),this.reconcileTimeoutState()}getAbortableStartupCursorCprState(){if(this.pending.length===0)return null;switch(this.state.tag){case"csi":{let bytes=this.pending.view(),firstParamStart=this.unitStart+2;if(this.cursor<firstParamStart)return null;let firstParamValue=null;for(let index=firstParamStart;index<this.cursor;index+=1){let byte=bytes[index];if(!isAsciiDigit(byte))return null;firstParamValue=(firstParamValue??0)*10+(byte-48)}return{tag:"csi_parametric_ignored",semicolons:0,segments:1,hasDigit:this.cursor>firstParamStart,firstParamValue}}case"csi_parametric":case"csi_parametric_deferred":if(!canStillBeStartupCursorCprPrefix(this.state)||this.protocolContext.explicitWidthCprActive&&canStillBeExplicitWidthCpr(this.state))return null;return{tag:"csi_parametric_ignored",semicolons:this.state.semicolons,segments:this.state.segments,hasDigit:this.state.hasDigit,firstParamValue:this.state.firstParamValue}}return null}abortPendingStartupCursorCpr(){this.ensureAlive();let nextState=this.getAbortableStartupCursorCprState();if(!nextState)return;if(this.state=nextState,this.pendingSinceMs===null)this.markPending();this.forceFlush=!1,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.pendingSinceMs!==null&&(nowMsValue<this.pendingSinceMs||nowMsValue-this.pendingSinceMs<this.timeoutMs))return;this.tryForceFlush()}tryForceFlush(){if(this.paste||this.pendingSinceMs===null||this.pending.length===0)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 firstParamStart=this.unitStart+2,firstParamEnd=this.cursor,firstParamValue=parsePositiveDecimalPrefix(bytes,firstParamStart,firstParamEnd);if(firstParamValue===null&&this.protocolContext.kittyKeyboardEnabled)firstParamValue=parseKittyFirstFieldCodepoint(bytes,firstParamStart,firstParamEnd);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,protocol=classifyParametricCsiProtocol(this.state,byte);this.emitKeyOrResponse(protocol,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_parametric_ignored":{if(this.cursor>=bytes.length){if(!this.forceFlush){this.markPending();return}this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(byte===ESC){this.state={tag:"ground"},this.consumePrefix(this.cursor);continue}if(isAsciiDigit(byte)){this.cursor+=1,this.state={tag:"csi_parametric_ignored",semicolons:this.state.semicolons,segments:this.state.segments,hasDigit:!0,firstParamValue:this.state.semicolons===0?(this.state.firstParamValue??0)*10+(byte-48):this.state.firstParamValue};continue}if(byte===59&&this.state.semicolons===0&&this.state.hasDigit){if(this.protocolContext.explicitWidthCprActive&&this.state.firstParamValue===1){this.state={tag:"csi"};continue}this.cursor+=1,this.state={tag:"csi_parametric_ignored",semicolons:1,segments:1,hasDigit:!1,firstParamValue:this.state.firstParamValue};continue}if(byte===82&&this.state.semicolons===1&&this.state.hasDigit){let end=this.cursor+1;this.state={tag:"ground"},this.consumePrefix(end);continue}if(this.state.semicolons===0){this.state={tag:"csi"};continue}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.emitOpaqueResponse("csi",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.tryForceFlush(),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[start3,end,,meta]=highlights[i2];if(start3===end)continue;if(meta?.containsInjection)injectionContainerRanges.push({start:start3,end});boundaries.push({offset:start3,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]===`
3183
- `){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 result2=await client.highlightOnce(content,filetype);if(result2.highlights&&result2.highlights.length>0){let chunks=treeSitterToTextChunks(content,result2.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((resolve23,reject)=>{if(scopeMap.has(id))clearTimeout(scopeMap.get(id));let timerId=setTimeout(()=>{try{resolve23(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:[resolve20(dirname32(fileURLToPath6(import.meta.url)),highlights_default)]},wasm:resolve20(dirname32(fileURLToPath6(import.meta.url)),tree_sitter_javascript_default)},{filetype:"typescript",aliases:["typescriptreact"],queries:{highlights:[resolve20(dirname32(fileURLToPath6(import.meta.url)),highlights_default2)]},wasm:resolve20(dirname32(fileURLToPath6(import.meta.url)),tree_sitter_typescript_default)},{filetype:"markdown",queries:{highlights:[resolve20(dirname32(fileURLToPath6(import.meta.url)),highlights_default3)],injections:[resolve20(dirname32(fileURLToPath6(import.meta.url)),injections_default)]},wasm:resolve20(dirname32(fileURLToPath6(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:[resolve20(dirname32(fileURLToPath6(import.meta.url)),highlights_default4)]},wasm:resolve20(dirname32(fileURLToPath6(import.meta.url)),tree_sitter_markdown_inline_default)},{filetype:"zig",queries:{highlights:[resolve20(dirname32(fileURLToPath6(import.meta.url)),highlights_default5)]},wasm:resolve20(dirname32(fileURLToPath6(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 join90(getBunfsRootPath(),basename13(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(path33){if(typeof path33!=="string")return;let basename22=getBasename(path33);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=path32.basename(source);let cacheFile=path32.join(cacheDir,cacheSubdir,cacheFileName);await mkdir13(path32.dirname(cacheFile),{recursive:!0});try{let cachedContent=await readFile18(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 writeFile12(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 readFile18(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 mkdir13(path32.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 writeFile12(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 readFile18(source);return await writeFile12(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((query2)=>query2.trim().length>0).join(`
3183
+ `){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 result2=await client.highlightOnce(content,filetype);if(result2.highlights&&result2.highlights.length>0){let chunks=treeSitterToTextChunks(content,result2.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((resolve23,reject)=>{if(scopeMap.has(id))clearTimeout(scopeMap.get(id));let timerId=setTimeout(()=>{try{resolve23(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:[resolve20(dirname33(fileURLToPath6(import.meta.url)),highlights_default)]},wasm:resolve20(dirname33(fileURLToPath6(import.meta.url)),tree_sitter_javascript_default)},{filetype:"typescript",aliases:["typescriptreact"],queries:{highlights:[resolve20(dirname33(fileURLToPath6(import.meta.url)),highlights_default2)]},wasm:resolve20(dirname33(fileURLToPath6(import.meta.url)),tree_sitter_typescript_default)},{filetype:"markdown",queries:{highlights:[resolve20(dirname33(fileURLToPath6(import.meta.url)),highlights_default3)],injections:[resolve20(dirname33(fileURLToPath6(import.meta.url)),injections_default)]},wasm:resolve20(dirname33(fileURLToPath6(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:[resolve20(dirname33(fileURLToPath6(import.meta.url)),highlights_default4)]},wasm:resolve20(dirname33(fileURLToPath6(import.meta.url)),tree_sitter_markdown_inline_default)},{filetype:"zig",queries:{highlights:[resolve20(dirname33(fileURLToPath6(import.meta.url)),highlights_default5)]},wasm:resolve20(dirname33(fileURLToPath6(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 join90(getBunfsRootPath(),basename13(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(path33){if(typeof path33!=="string")return;let basename22=getBasename(path33);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=path32.basename(source);let cacheFile=path32.join(cacheDir,cacheSubdir,cacheFileName);await mkdir12(path32.dirname(cacheFile),{recursive:!0});try{let cachedContent=await readFile18(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 writeFile12(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 readFile18(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 mkdir12(path32.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 writeFile12(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 readFile18(source);return await writeFile12(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((query2)=>query2.trim().length>0).join(`
3184
3184
  `)}static async fetchHighlightQuery(source,cacheDir,filetype){let result2=await this.downloadOrLoad(source,cacheDir,"queries",".scm",!0,filetype);if(result2.error)return console.error(`Error fetching highlight query from ${source}:`,result2.error),"";if(result2.content)return new TextDecoder().decode(result2.content);return""}}function getDefaultOptions(){return{configPath:path4.resolve(__dirname4,"../parsers-config"),assetsDir:path4.resolve(__dirname4),outputPath:path4.resolve(__dirname4,"../default-parsers.ts")}}async function loadConfig2(configPath2){let ext=path4.extname(configPath2),resolvedConfigPath=configPath2;if(ext===""){let file=(await readdir12(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),result2=await DownloadUtils.downloadToPath(languageUrl,languagePath);if(result2.error)throw Error(`Failed to download language for ${filetype}: ${result2.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(`
3185
3185
  `).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}
3186
3186
  ${content}`),console.log(` \u2713 Downloaded ${content.split(`
@@ -4018,7 +4018,7 @@ Bus `);for(let i2=1;i2<parts.length;i2++){let usb2=parseLinuxUsb(parts[i2]);resu
4018
4018
  `),service=util4.getValue(lines,"Service",":"),errorCode=util4.getValue(lines,"ConfigManagerErrorCode",":");if(util4.getValue(lines,"PNPClass",":").toLowerCase()==="bluetooth"&&errorCode==="0"&&service==="")result2.push(parseWindowsBluetooth(lines))});if(callback)callback(result2);resolve23(result2)});if(_freebsd||_netbsd||_openbsd||_sunos)resolve23(null)})})}exports.bluetoothDevices=bluetoothDevices});var require_lib5=__commonJS((exports)=>{var lib_version=require_package().version,util4=require_util3(),system=require_system(),osInfo=require_osinfo(),cpu=require_cpu(),memory=require_memory(),battery=require_battery(),graphics=require_graphics(),filesystem=require_filesystem(),network=require_network(),wifi=require_wifi(),processes=require_processes(),users=require_users(),internet=require_internet(),docker=require_docker(),vbox=require_virtualbox(),printer=require_printer(),usb=require_usb(),audio=require_audio(),bluetooth=require_bluetooth(),_platform=process.platform,_windows=_platform==="win32",_freebsd=_platform==="freebsd",_openbsd=_platform==="openbsd",_netbsd=_platform==="netbsd",_sunos=_platform==="sunos";if(_windows)util4.getCodepage(),util4.getPowershell();function version(){return lib_version}function getStaticData(callback){return new Promise((resolve23)=>{process.nextTick(()=>{let data={};data.version=version(),Promise.all([system.system(),system.bios(),system.baseboard(),system.chassis(),osInfo.osInfo(),osInfo.uuid(),osInfo.versions(),cpu.cpu(),cpu.cpuFlags(),graphics.graphics(),network.networkInterfaces(),memory.memLayout(),filesystem.diskLayout(),audio.audio(),bluetooth.bluetoothDevices(),usb.usb(),printer.printer()]).then((res)=>{if(data.system=res[0],data.bios=res[1],data.baseboard=res[2],data.chassis=res[3],data.os=res[4],data.uuid=res[5],data.versions=res[6],data.cpu=res[7],data.cpu.flags=res[8],data.graphics=res[9],data.net=res[10],data.memLayout=res[11],data.diskLayout=res[12],data.audio=res[13],data.bluetooth=res[14],data.usb=res[15],data.printer=res[16],callback)callback(data);resolve23(data)})})})}function getDynamicData(srv,iface,callback){if(util4.isFunction(iface))callback=iface,iface="";if(util4.isFunction(srv))callback=srv,srv="";return new Promise((resolve23)=>{process.nextTick(()=>{iface=iface||network.getDefaultNetworkInterface(),srv=srv||"";let functionProcessed=(()=>{let totalFunctions=15;if(_windows)totalFunctions=13;if(_freebsd||_openbsd||_netbsd)totalFunctions=11;if(_sunos)totalFunctions=6;return function(){if(--totalFunctions===0){if(callback)callback(data);resolve23(data)}}})(),data={};if(data.time=osInfo.time(),data.node=process.versions.node,data.v8=process.versions.v8,cpu.cpuCurrentSpeed().then((res)=>{data.cpuCurrentSpeed=res,functionProcessed()}),users.users().then((res)=>{data.users=res,functionProcessed()}),processes.processes().then((res)=>{data.processes=res,functionProcessed()}),cpu.currentLoad().then((res)=>{data.currentLoad=res,functionProcessed()}),!_sunos)cpu.cpuTemperature().then((res)=>{data.temp=res,functionProcessed()});if(!_openbsd&&!_freebsd&&!_netbsd&&!_sunos)network.networkStats(iface).then((res)=>{data.networkStats=res,functionProcessed()});if(!_sunos)network.networkConnections().then((res)=>{data.networkConnections=res,functionProcessed()});if(memory.mem().then((res)=>{data.mem=res,functionProcessed()}),!_sunos)battery().then((res)=>{data.battery=res,functionProcessed()});if(!_sunos)processes.services(srv).then((res)=>{data.services=res,functionProcessed()});if(!_sunos)filesystem.fsSize().then((res)=>{data.fsSize=res,functionProcessed()});if(!_windows&&!_openbsd&&!_freebsd&&!_netbsd&&!_sunos)filesystem.fsStats().then((res)=>{data.fsStats=res,functionProcessed()});if(!_windows&&!_openbsd&&!_freebsd&&!_netbsd&&!_sunos)filesystem.disksIO().then((res)=>{data.disksIO=res,functionProcessed()});if(!_openbsd&&!_freebsd&&!_netbsd&&!_sunos)wifi.wifiNetworks().then((res)=>{data.wifiNetworks=res,functionProcessed()});internet.inetLatency().then((res)=>{data.inetLatency=res,functionProcessed()})})})}function getAllData(srv,iface,callback){return new Promise((resolve23)=>{process.nextTick(()=>{let data={};if(iface&&util4.isFunction(iface)&&!callback)callback=iface,iface="";if(srv&&util4.isFunction(srv)&&!iface&&!callback)callback=srv,srv="",iface="";getStaticData().then((res)=>{data=res,getDynamicData(srv,iface).then((res2)=>{for(let key in res2)if({}.hasOwnProperty.call(res2,key))data[key]=res2[key];if(callback)callback(data);resolve23(data)})})})})}function get3(valueObject,callback){return new Promise((resolve23)=>{process.nextTick(()=>{let allPromises=Object.keys(valueObject).filter((func)=>({}).hasOwnProperty.call(exports,func)).map((func)=>{let params=valueObject[func].substring(valueObject[func].lastIndexOf("(")+1,valueObject[func].lastIndexOf(")")),funcWithoutParams=func.indexOf(")")>=0?func.split(")")[1].trim():func;if(funcWithoutParams=func.indexOf("|")>=0?func.split("|")[0].trim():funcWithoutParams,params)return exports[funcWithoutParams](params);else return exports[funcWithoutParams]("")});Promise.all(allPromises).then((data)=>{let result2={},i2=0;for(let key in valueObject)if({}.hasOwnProperty.call(valueObject,key)&&{}.hasOwnProperty.call(exports,key)&&data.length>i2){if(valueObject[key]==="*"||valueObject[key]==="all")result2[key]=data[i2];else{let keys=valueObject[key],filter="",filterParts=[];if(keys.indexOf(")")>=0)keys=keys.split(")")[1].trim();if(keys.indexOf("|")>=0)filter=keys.split("|")[1].trim(),filterParts=filter.split(":"),keys=keys.split("|")[0].trim();if(keys=keys.replace(/,/g," ").replace(/ +/g," ").split(" "),data[i2])if(Array.isArray(data[i2])){let partialArray=[];data[i2].forEach((element)=>{let partialRes={};if(keys.length===1&&(keys[0]==="*"||keys[0]==="all"))partialRes=element;else keys.forEach((k2)=>{if({}.hasOwnProperty.call(element,k2))partialRes[k2]=element[k2]});if(filter&&filterParts.length===2){if({}.hasOwnProperty.call(partialRes,filterParts[0].trim())){let val=partialRes[filterParts[0].trim()];if(typeof val==="number"){if(val===parseFloat(filterParts[1].trim()))partialArray.push(partialRes)}else if(typeof val==="string"){if(val.toLowerCase()===filterParts[1].trim().toLowerCase())partialArray.push(partialRes)}}}else partialArray.push(partialRes)}),result2[key]=partialArray}else{let partialRes={};keys.forEach((k2)=>{if({}.hasOwnProperty.call(data[i2],k2))partialRes[k2]=data[i2][k2]}),result2[key]=partialRes}else result2[key]={}}i2++}if(callback)callback(result2);resolve23(result2)})})})}function observe(valueObject,interval,callback){let _data=null;return setInterval(()=>{get3(valueObject).then((data)=>{if(JSON.stringify(_data)!==JSON.stringify(data))_data=Object.assign({},data),callback(data)})},interval)}exports.version=version;exports.system=system.system;exports.bios=system.bios;exports.baseboard=system.baseboard;exports.chassis=system.chassis;exports.time=osInfo.time;exports.osInfo=osInfo.osInfo;exports.versions=osInfo.versions;exports.shell=osInfo.shell;exports.uuid=osInfo.uuid;exports.cpu=cpu.cpu;exports.cpuFlags=cpu.cpuFlags;exports.cpuCache=cpu.cpuCache;exports.cpuCurrentSpeed=cpu.cpuCurrentSpeed;exports.cpuTemperature=cpu.cpuTemperature;exports.currentLoad=cpu.currentLoad;exports.fullLoad=cpu.fullLoad;exports.mem=memory.mem;exports.memLayout=memory.memLayout;exports.battery=battery;exports.graphics=graphics.graphics;exports.fsSize=filesystem.fsSize;exports.fsOpenFiles=filesystem.fsOpenFiles;exports.blockDevices=filesystem.blockDevices;exports.fsStats=filesystem.fsStats;exports.disksIO=filesystem.disksIO;exports.diskLayout=filesystem.diskLayout;exports.networkInterfaceDefault=network.networkInterfaceDefault;exports.networkGatewayDefault=network.networkGatewayDefault;exports.networkInterfaces=network.networkInterfaces;exports.networkStats=network.networkStats;exports.networkConnections=network.networkConnections;exports.wifiNetworks=wifi.wifiNetworks;exports.wifiInterfaces=wifi.wifiInterfaces;exports.wifiConnections=wifi.wifiConnections;exports.services=processes.services;exports.processes=processes.processes;exports.processLoad=processes.processLoad;exports.users=users.users;exports.inetChecksite=internet.inetChecksite;exports.inetLatency=internet.inetLatency;exports.dockerInfo=docker.dockerInfo;exports.dockerImages=docker.dockerImages;exports.dockerContainers=docker.dockerContainers;exports.dockerContainerStats=docker.dockerContainerStats;exports.dockerContainerProcesses=docker.dockerContainerProcesses;exports.dockerVolumes=docker.dockerVolumes;exports.dockerAll=docker.dockerAll;exports.vboxInfo=vbox.vboxInfo;exports.printer=printer.printer;exports.usb=usb.usb;exports.audio=audio.audio;exports.bluetoothDevices=bluetooth.bluetoothDevices;exports.getStaticData=getStaticData;exports.getDynamicData=getDynamicData;exports.getAllData=getAllData;exports.get=get3;exports.observe=observe;exports.powerShellStart=util4.powerShellStart;exports.powerShellRelease=util4.powerShellRelease});import os4 from"os";function toGB(bytes){return Math.round(bytes/1073741824*10)/10}function bar(percent,width){let p=Math.max(0,Math.min(100,percent)),filled=Math.round(p/100*width);return`[${"=".repeat(filled)}${"-".repeat(width-filled)}]`}function pickColor(percent){if(percent>90)return palette.error;if(percent>70)return palette.warning;return palette.accent}function SystemStatsView({stats:stats2}){if(!stats2)return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",paddingX:1,backgroundColor:palette.bgRaised,children:import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.accent,children:"genie"},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:` v${VERSION}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this);let{cpu,ram,swap,load:load3}=stats2,hotStr=cpu.hotCores.map((c)=>`#${c.id} ${c.load}%`).join(" ");return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",paddingX:1,backgroundColor:palette.bgRaised,children:[import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.accent,children:"genie"},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:` v${VERSION}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:"CPU "},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:pickColor(cpu.combined),children:`${String(cpu.combined).padStart(3)}% ${bar(cpu.combined,8)}`},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:` ${cpu.coreCount}c`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:" hot "},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.warning,children:hotStr},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:"RAM "},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:pickColor(ram.percent),children:`${ram.usedGB}/${ram.totalGB}G ${bar(ram.percent,8)}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),swap.totalGB>0?import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:"SWP "},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:pickColor(swap.percent),children:`${swap.usedGB}/${swap.totalGB}G ${bar(swap.percent,8)}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this):null,import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:"Load "},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:pickColor(load3.percent),children:`${load3.percent}%`},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:` (${load3.busy}/${load3.total} busy)`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function SystemStats(){let[stats2,setStats]=import_react27.useState(null),mountedRef=import_react27.useRef(!0);return import_react27.useEffect(()=>{mountedRef.current=!0;async function refresh(){try{let[cpu,mem]=await Promise.all([import_systeminformation.default.currentLoad(),import_systeminformation.default.mem()]);if(!mountedRef.current)return;let coreCount=os4.cpus().length,avg1=os4.loadavg()[0],sorted=cpu.cpus.map((c,i2)=>({id:i2,load:Math.round(c.load)})).sort((a,b3)=>b3.load-a.load);setStats({cpu:{combined:Math.round(cpu.currentLoad),hotCores:sorted.slice(0,3),coreCount},ram:{usedGB:toGB(mem.active),totalGB:toGB(mem.total),percent:mem.total>0?Math.round(mem.active/mem.total*100):0},swap:{usedGB:toGB(mem.swapused),totalGB:toGB(mem.swaptotal),percent:mem.swaptotal>0?Math.round(mem.swapused/mem.swaptotal*100):0},load:{percent:coreCount>0?Math.round(avg1/coreCount*100):0,busy:Math.round(avg1*10)/10,total:coreCount}})}catch{}}refresh();let timer2=setInterval(refresh,3000);return()=>{mountedRef.current=!1,clearInterval(timer2)}},[]),import_jsx_dev_runtime2.jsxDEV(SystemStatsView,{stats:stats2},void 0,!1,void 0,this)}var import_react27,import_systeminformation;var init_SystemStats=__esm(()=>{init_version();init_theme2();init_jsx_dev_runtime();import_react27=__toESM(require_react_development(),1),import_systeminformation=__toESM(require_lib5(),1)});function validateName(name){if(name.length===0)return null;try{return validateBranchName(name),null}catch(err){return err instanceof Error?err.message:String(err)}}function TeamCreate({availableAgents,workspaceRoot,onConfirm,onCancel}){let[step,setStep]=import_react29.useState("name"),[teamName,setTeamName]=import_react29.useState(""),[selected,setSelected]=import_react29.useState(()=>new Set),[memberCursor,setMemberCursor]=import_react29.useState(0),nameError=import_react29.useMemo(()=>validateName(teamName),[teamName]),nameValid=teamName.length>0&&nameError===null,intent=import_react29.useMemo(()=>({kind:"create-team",name:teamName.length>0?teamName:"TEAM_NAME",repo:workspaceRoot}),[teamName,workspaceRoot]),handleNameChange=import_react29.useCallback((value)=>{setTeamName(value)},[]),advanceFromName=import_react29.useCallback(()=>{if(!nameValid)return;setStep("members")},[nameValid]),toggleMember=import_react29.useCallback((name)=>{setSelected((prev)=>{let next=new Set(prev);if(next.has(name))next.delete(name);else next.add(name);return next})},[]),confirmMembers=import_react29.useCallback(()=>{onConfirm({teamName,members:Array.from(selected)})},[onConfirm,teamName,selected]);return useKeyboard((key)=>{if(step==="name"){handleNameStepKey(key,{onCancel,nameValid,advanceFromName});return}handleMembersStepKey(key,{availableAgents,memberCursor,setStep,setMemberCursor,toggleMember,confirmMembers})}),import_jsx_dev_runtime2.jsxDEV("box",{position:"absolute",width:"100%",height:"100%",justifyContent:"center",alignItems:"center",backgroundColor:palette.bgOverlay,children:import_jsx_dev_runtime2.jsxDEV("box",{border:!0,borderColor:palette.borderActive,backgroundColor:palette.bgRaised,paddingX:3,paddingY:1,flexDirection:"column",width:"100%",gap:1,children:[import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.accent,children:"New team"},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:step==="name"?" \u2014 step 1 of 2":" \u2014 step 2 of 2"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),step==="name"?import_jsx_dev_runtime2.jsxDEV(NameStep,{value:teamName,onChange:handleNameChange,onSubmit:advanceFromName,errorMessage:nameError},void 0,!1,void 0,this):import_jsx_dev_runtime2.jsxDEV(MembersStep,{agents:availableAgents,selected,cursor:memberCursor},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV(CliPreviewLine,{intent,hint:step==="name"?"Enter: next \xB7 Esc: cancel":"Space: toggle \xB7 Enter: create \xB7 Esc: back"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function NameStep({value,onChange,onSubmit,errorMessage}){return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",gap:1,children:[import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:"Team name (git-branch-safe):"},void 0,!1,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("input",{value,onInput:onChange,onChange,onSubmit,focused:!0,placeholder:"feat/auth-bug",backgroundColor:palette.bg,textColor:palette.text,placeholderColor:palette.textMuted},void 0,!1,void 0,this),errorMessage!==null?import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:`\u26A0 ${errorMessage}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function MembersStep({agents,selected,cursor}){if(agents.length===0)return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",children:[import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:"No agents registered"},void 0,!1,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:"Members can be hired later via `genie team hire`."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",children:[import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:"Select members (space to toggle):"},void 0,!1,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",children:agents.map((name,idx)=>{let isSelected=selected.has(name),isCursor=idx===cursor,tick=isSelected?"[x]":"[ ]",prefix=isCursor?"\u25B6 ":" ";return import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:isCursor?palette.accent:palette.textMuted,children:prefix},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:isSelected?palette.success:palette.textDim,children:tick},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.text,children:` ${name}`},void 0,!1,void 0,this)]},name,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function isEnter(key){return key.name==="enter"||key.name==="return"}function handleNameStepKey(key,opts){if(key.name==="escape"){opts.onCancel();return}if(isEnter(key)&&opts.nameValid)opts.advanceFromName()}function handleMembersStepKey(key,opts){if(key.name==="escape"){opts.setStep("name");return}if(opts.availableAgents.length===0){if(isEnter(key))opts.confirmMembers();return}if(key.name==="up"||key.name==="k"){opts.setMemberCursor((prev)=>prev<=0?opts.availableAgents.length-1:prev-1);return}if(key.name==="down"||key.name==="j"){opts.setMemberCursor((prev)=>prev>=opts.availableAgents.length-1?0:prev+1);return}if(key.name==="space"){let name=opts.availableAgents[opts.memberCursor];if(name)opts.toggleMember(name);return}if(isEnter(key))opts.confirmMembers()}var import_react29;var init_TeamCreate=__esm(async()=>{init_team_manager();init_theme2();init_CliPreviewLine();init_jsx_dev_runtime();await init_react2();import_react29=__toESM(require_react_development(),1)});function getNodeIcon(node){if(node.type==="agent")return getAgentIcon(node);switch(node.type){case"session":return node.data.attached?"\u25B6":"\u25B8";case"window":return node.data.active?"\u25A0":"\u25A1";case"pane":return getPaneIcon(node);default:return" "}}function getAgentIcon(node){switch(node.workState){case"in_flight":return"\u25C6";case"paused":return"\u25D0";case"done":return"\u2714";case"stuck":return"\u2718";default:break}switch(node.wsAgentState){case"running":return"\u25CF";case"stopped":return"\u25CC";case"error":return"\u2298";case"spawning":return"\u231B";default:return"\u25CC"}}function getPaneIcon(node){if(node.data.isDead)return"\u2718";if(node.agentState==="working")return"\u25CF";if(node.agentState==="idle")return"\u25CB";if(node.agentState==="permission")return"\u26A0";if(node.agentState==="error")return"\u2718";if(node.data.isClaudeLike)return"\u25C6";return"\u25CB"}function getNodeColor(node){if(node.type==="agent")return getAgentColor(node);switch(node.type){case"session":return node.data.attached?palette.success:palette.textDim;case"window":return node.data.active?palette.info:palette.text;case"pane":return getPaneColor(node);default:return palette.text}}function getAgentColor(node){switch(node.workState){case"in_flight":return palette.accentBright;case"paused":return palette.textDim;case"done":return palette.info;case"stuck":return palette.error;default:break}switch(node.wsAgentState){case"running":return palette.success;case"stopped":return palette.text;case"error":return palette.error;case"spawning":return palette.warning;default:return palette.textDim}}function getPaneColor(node){if(node.data.isDead)return palette.error;if(node.agentState==="working")return palette.info;if(node.agentState==="permission")return palette.warning;if(node.agentState==="error")return palette.error;if(node.agentState==="idle")return palette.textDim;if(node.data.isClaudeLike)return palette.info;return palette.textDim}function getAgentSuffix(node){if(node.workState==="stuck")return" [stuck \u2014 press R to retry]";if(node.workState==="paused")return" [paused \u2014 auto-resume off]";if(node.workState==="done")return" [done]";if(node.wsAgentState==="spawning"&&node.activePanes===0)return" [stuck \u2014 press R to retry]";if(node.wsAgentState==="stopped")return" [Enter to start]";let wc=node.data.windowCount;if(wc>1)return` (${wc} windows)`;if(wc===1)return" (1 window)";return""}function getNodeSuffix(node){if(node.type==="agent")return getAgentSuffix(node);if(node.type==="session"||node.type==="pane"){let count=node.activePanes;if(count>0)return` ${icons.agent}${count}`}return""}function getStateColor(state){switch(state){case"working":return palette.info;case"idle":return palette.textDim;case"permission":return palette.warning;case"error":return palette.error;default:return palette.textMuted}}var import_react30,TreeNodeRow;var init_TreeNode=__esm(()=>{init_theme2();init_jsx_dev_runtime();import_react30=__toESM(require_react_development(),1),TreeNodeRow=import_react30.memo(function({node,selected,onSelect,onToggle,onContextMenu}){let indent2=" ".repeat(node.depth),hasChildren=node.children.length>0,expandIcon=hasChildren?node.expanded?icons.expanded:icons.collapsed:" ",icon=getNodeIcon(node),color2=getNodeColor(node),suffix2=getNodeSuffix(node),labelColor=selected?palette.accentBright:node.type==="agent"&&node.kind==="subagent"?palette.textDim:palette.text;return import_jsx_dev_runtime2.jsxDEV("box",{height:1,width:"100%",backgroundColor:selected?palette.accentDim:void 0,onMouseDown:(event)=>{if(event.button===2&&onContextMenu){onSelect(node.id),onContextMenu(node.id);return}if(onSelect(node.id),hasChildren)onToggle(node.id)},children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:[indent2,expandIcon," "]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:color2,children:[icon," "]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:labelColor,children:node.label},void 0,!1,void 0,this),suffix2?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:suffix2},void 0,!1,void 0,this):null,node.agentState?import_jsx_dev_runtime2.jsxDEV("span",{fg:getStateColor(node.agentState),children:[" ",node.agentState]},void 0,!0,void 0,this):null,process.env.GENIE_TUI_DEBUG==="1"?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:` [${node.type}]`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)})});function useDiagnosticsRefresh(setDiagnostics,setRequestedInitialAgent){import_react32.useEffect(()=>{let active=!0,lastErrorMessage=null,lastErrorLoggedAt=0;async function refresh(){try{let snap=await collectDiagnostics();if(!active)return;setDiagnostics(snap),lastErrorMessage=null;let signaledAgent=consumeInitialAgentSignal();if(signaledAgent)setRequestedInitialAgent(signaledAgent)}catch(err){let message=err instanceof Error?err.message:String(err),now=Date.now();if(message!==lastErrorMessage||now-lastErrorLoggedAt>30000)console.error("TUI: diagnostics failed:",message),lastErrorMessage=message,lastErrorLoggedAt=now}}refresh();let timer2=setInterval(refresh,2000);return()=>{active=!1,clearInterval(timer2)}},[setDiagnostics,setRequestedInitialAgent])}function useSessionTreeBuilder(diagnostics,workspaceRoot,setSessionTree){import_react32.useEffect(()=>{if(!diagnostics)return;let newTree;if(workspaceRoot){let agentNames=scanAgents2(workspaceRoot);newTree=buildWorkspaceTree({agentNames,sessions:diagnostics.sessions,executors:diagnostics.executors,workStates:diagnostics.workStates,teamScope:process.env.GENIE_TUI_TEAM??process.env.GENIE_TEAM})}else newTree=buildSessionTree(diagnostics);setSessionTree((prev)=>mergeExpandedState(prev,newTree))},[diagnostics,workspaceRoot,setSessionTree])}function useStableSelection(flatNodes,selectedIndex,setSelectedIndex,selectedNodeId){import_react32.useEffect(()=>{let node=flatNodes[selectedIndex]?.node;if(node)selectedNodeId.current=node.id},[selectedIndex,flatNodes,selectedNodeId]),import_react32.useLayoutEffect(()=>{if(flatNodes.length===0)return;if(selectedIndex>=flatNodes.length){setSelectedIndex(flatNodes.length-1);return}if(!selectedNodeId.current)return;let currentAtIndex=flatNodes[selectedIndex]?.node;if(currentAtIndex&&currentAtIndex.id===selectedNodeId.current)return;let restored=flatNodes.findIndex((n)=>n.node.id===selectedNodeId.current);if(restored>=0)setSelectedIndex(restored)},[flatNodes])}function useInitialAgentSelection(requestedInitialAgent,flatNodes,setSelectedIndex,setRequestedInitialAgent,onTmuxSessionSelect){import_react32.useEffect(()=>{if(!requestedInitialAgent||flatNodes.length===0)return;let idx=flatNodes.findIndex((n)=>n.node.id===`agent:${requestedInitialAgent}`);if(idx<0)return;setSelectedIndex(idx);let node=flatNodes[idx].node;if(node.type==="agent"&&node.wsAgentState!=="running"&&node.wsAgentState!=="spawning")spawnAgent(agentNameFromNode(node),onTmuxSessionSelect);setRequestedInitialAgent(void 0)},[requestedInitialAgent,flatNodes,onTmuxSessionSelect,setSelectedIndex,setRequestedInitialAgent])}function useAutoAttach(flatNodes,selectedIndex,lastTarget,onTmuxSessionSelect){import_react32.useEffect(()=>{let current=flatNodes[selectedIndex]?.node;if(!current)return;let target=getSessionTarget(current);if(!target)return;if(current.type==="agent"&&current.wsAgentState!=="running")return;let key=`${target.sessionName}:${target.windowIndex??""}`;if(key===lastTarget.current)return;lastTarget.current=key,onTmuxSessionSelect(target.sessionName,target.windowIndex)},[selectedIndex,flatNodes,onTmuxSessionSelect,lastTarget])}function useNavKeyboard(opts){useKeyboard((key)=>{if(opts.keyboardDisabled)return;if(opts.spawnIntoAgent!==null||opts.spawnPickerTarget!==null)return;if(tryOpenTeamCreate(key,{workspaceRoot:opts.workspaceRoot,showTeamCreate:opts.showTeamCreate,contextMenuNodeId:opts.contextMenuNodeId,handleOpenTeamCreate:opts.handleOpenTeamCreate}))return;if(opts.showTeamCreate)return;handleKeyboardInput(key,opts)})}function renderAlertBadge(alertCount){if(alertCount<=0)return null;return import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.error,children:[" ","\u25CF ",alertCount," alert",alertCount===1?"":"s"]},void 0,!0,void 0,this)}function countAgents(nodes,predicate){let count=0;for(let n of nodes){if(n.type==="agent"&&predicate(n))count++;if(n.children.length>0)count+=countAgents(n.children,predicate)}return count}function computeNavCounts(workspaceRoot,sessionTree,diagnostics){if(workspaceRoot){let agentCount=countAgents(sessionTree,()=>!0);if(agentCount>0)return{agentCount,runningCount:countAgents(sessionTree,(n)=>n.wsAgentState==="running")}}let paneSum=diagnostics?.sessions.reduce((sum,s2)=>sum+s2.windows.reduce((ws,w2)=>ws+w2.panes.length,0),0)??0;return{agentCount:diagnostics?.sessions.length??0,runningCount:paneSum}}function Nav({onTmuxSessionSelect,onNewAgentWindow,workspaceRoot,initialAgent,keyboardDisabled=!1}){let[diagnostics,setDiagnostics]=import_react32.useState(null),[sessionTree,setSessionTree]=import_react32.useState([]),[selectedIndex,setSelectedIndex]=import_react32.useState(0),[requestedInitialAgent,setRequestedInitialAgent]=import_react32.useState(initialAgent),[contextMenuNodeId,setContextMenuNodeId]=import_react32.useState(null),[spawnIntoAgent,setSpawnIntoAgent]=import_react32.useState(null),[spawnPickerTarget,setSpawnPickerTarget]=import_react32.useState(null),lastTarget=import_react32.useRef(null),selectedNodeId=import_react32.useRef(null);useDiagnosticsRefresh(setDiagnostics,setRequestedInitialAgent),useSessionTreeBuilder(diagnostics,workspaceRoot,setSessionTree);let flatNodes=import_react32.useMemo(()=>flattenTree(sessionTree),[sessionTree]);useStableSelection(flatNodes,selectedIndex,setSelectedIndex,selectedNodeId),useInitialAgentSelection(requestedInitialAgent,flatNodes,setSelectedIndex,setRequestedInitialAgent,onTmuxSessionSelect),useAutoAttach(flatNodes,selectedIndex,lastTarget,onTmuxSessionSelect);let handleSelect=import_react32.useCallback((id)=>{let idx=flatNodes.findIndex((n)=>n.node.id===id);if(idx>=0)setSelectedIndex(idx)},[flatNodes]),handleToggle=import_react32.useCallback((id)=>{setSessionTree((prev)=>toggleNode(prev,id))},[]),handleVerticalNav=import_react32.useCallback((keyName2)=>{let rowCount=flatNodes.length;if(rowCount===0)return;if(keyName2==="up"||keyName2==="k")setSelectedIndex((prev)=>prev===0?rowCount-1:prev-1);else if(keyName2==="down"||keyName2==="j")setSelectedIndex((prev)=>prev>=rowCount-1?0:prev+1)},[flatNodes.length]),handleExpandCollapse=import_react32.useCallback((keyName2)=>{let node=flatNodes[selectedIndex]?.node;if(!node)return;if((keyName2==="right"||keyName2==="l")&&node.children.length>0&&!node.expanded)handleToggle(node.id);else if((keyName2==="left"||keyName2==="h")&&node.expanded)handleToggle(node.id)},[flatNodes,selectedIndex,handleToggle]),handleEnter=import_react32.useCallback(()=>{let node=flatNodes[selectedIndex]?.node;if(!node)return;if(node.type==="agent"){handleEnterAgent(node,onTmuxSessionSelect);return}if(node.children.length>0)handleToggle(node.id);let target=getSessionTarget(node);if(target)onTmuxSessionSelect(target.sessionName,target.windowIndex)},[flatNodes,selectedIndex,handleToggle,onTmuxSessionSelect]),handleRetry=import_react32.useCallback(()=>{let node=flatNodes[selectedIndex]?.node;if(!node||node.type!=="agent")return;if(node.wsAgentState!=="spawning"&&node.wsAgentState!=="error")return;(async()=>{try{let{reconcileStaleSpawns:reconcileStaleSpawns2}=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry));await reconcileStaleSpawns2()}catch{}spawnAgent(agentNameFromNode(node),onTmuxSessionSelect)})()},[flatNodes,selectedIndex,onTmuxSessionSelect]),handleContextMenu=import_react32.useCallback((nodeId)=>{let flat=flatNodes.find((n)=>n.node.id===nodeId);if(flat&&buildMenuItems(flat.node).length>0)setContextMenuNodeId(nodeId)},[flatNodes]),handleContextMenuAction=import_react32.useCallback((action,payload)=>{let node=flatNodes.find((n)=>n.node.id===contextMenuNodeId)?.node;if(!node)return;if(setContextMenuNodeId(null),action==="spawn-here"){let target=resolveSpawnHereTarget(node);if(target)setSpawnPickerTarget(target);return}dispatchContextMenuAction(action,node,payload,{sessionTree,onTmuxSessionSelect,onNewAgentWindow,openSpawnInto:setSpawnIntoAgent})},[flatNodes,contextMenuNodeId,sessionTree,onTmuxSessionSelect,onNewAgentWindow]),handleSpawnIntoConfirm=import_react32.useCallback((intent)=>{executeSpawnIntent(intent),setSpawnIntoAgent(null)},[]),handleSpawnIntoCancel=import_react32.useCallback(()=>{setSpawnIntoAgent(null)},[]),handleSpawnPickerConfirm=import_react32.useCallback((intent)=>{setSpawnPickerTarget(null),executeSpawnIntent(intent)},[]),handleSpawnPickerCancel=import_react32.useCallback(()=>{setSpawnPickerTarget(null)},[]),_menuDisabled=keyboardDisabled||contextMenuNodeId!==null,{showTeamCreate,handleOpenTeamCreate,handleTeamCreateConfirm,handleTeamCreateCancel}=useTeamCreateControls({workspaceRoot,diagnostics,onTmuxSessionSelect});useNavKeyboard({keyboardDisabled,spawnIntoAgent,spawnPickerTarget,workspaceRoot,showTeamCreate,contextMenuNodeId,handleOpenTeamCreate,flatNodes,selectedIndex,setContextMenuNodeId,handleVerticalNav,handleExpandCollapse,handleEnter,handleRetry,onNewAgentWindow});let{agentCount,runningCount}=computeNavCounts(workspaceRoot,sessionTree,diagnostics),headerLabel=workspaceRoot?"Agents":"Sessions",alertCount=diagnostics?.alertCount??0;return import_jsx_dev_runtime2.jsxDEV("box",{flexDirection:"column",width:"100%",height:"100%",backgroundColor:palette.bg,children:[import_jsx_dev_runtime2.jsxDEV("box",{height:1,paddingX:1,backgroundColor:palette.bgRaised,children:import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.accent,children:headerLabel},void 0,!1,void 0,this),diagnostics?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:[" ",workspaceRoot?`${runningCount}/${agentCount}`:`${agentCount}s ${runningCount}p`]},void 0,!0,void 0,this):null,renderAlertBadge(alertCount)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),diagnostics?import_jsx_dev_runtime2.jsxDEV("scrollbox",{focused:!0,height:"100%",style:{scrollbarOptions:{showArrows:!1,trackOptions:{foregroundColor:palette.scrollThumb,backgroundColor:palette.scrollTrack}}},children:flatNodes.map((flat,i2)=>import_jsx_dev_runtime2.jsxDEV(TreeNodeRow,{node:flat.node,selected:i2===selectedIndex,onSelect:handleSelect,onToggle:handleToggle,onContextMenu:handleContextMenu},flat.node.id,!1,void 0,this))},void 0,!1,void 0,this):import_jsx_dev_runtime2.jsxDEV("box",{flexGrow:1,justifyContent:"center",alignItems:"center",flexDirection:"column",gap:1,children:[import_jsx_dev_runtime2.jsxDEV("ascii-font",{text:"GENIE",font:"tiny",color:palette.accent},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("text",{fg:palette.textDim,children:"Collecting..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),contextMenuNodeId?import_jsx_dev_runtime2.jsxDEV(ContextMenu,{items:buildMenuItems(flatNodes.find((n)=>n.node.id===contextMenuNodeId)?.node??{}),onAction:handleContextMenuAction,onClose:()=>setContextMenuNodeId(null),positionY:flatNodes.findIndex((n)=>n.node.id===contextMenuNodeId)+1},void 0,!1,void 0,this):null,spawnIntoAgent!==null?import_jsx_dev_runtime2.jsxDEV(SpawnTargetPicker,{agentName:spawnIntoAgent,sessions:diagnostics?.sessions??[],onConfirm:handleSpawnIntoConfirm,onCancel:handleSpawnIntoCancel},void 0,!1,void 0,this):null,spawnPickerTarget!==null?import_jsx_dev_runtime2.jsxDEV(AgentPicker,{target:spawnPickerTarget,onConfirm:handleSpawnPickerConfirm,onCancel:handleSpawnPickerCancel},void 0,!1,void 0,this):null,showTeamCreate?import_jsx_dev_runtime2.jsxDEV(TeamCreate,{availableAgents:workspaceRoot?scanAgents2(workspaceRoot):[],workspaceRoot,onConfirm:handleTeamCreateConfirm,onCancel:handleTeamCreateCancel},void 0,!1,void 0,this):null,import_jsx_dev_runtime2.jsxDEV(SystemStats,{},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("box",{height:1,paddingX:1,backgroundColor:palette.bgRaised,children:import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:buildFooterHint(workspaceRoot)},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function useTeamCreateControls(opts){let{workspaceRoot,diagnostics,onTmuxSessionSelect}=opts,[showTeamCreate,setShowTeamCreate]=import_react32.useState(!1),pendingTeamNameRef=import_react32.useRef(null),handleOpenTeamCreate=import_react32.useCallback(()=>{if(!workspaceRoot)return;setShowTeamCreate(!0)},[workspaceRoot]),handleTeamCreateConfirm=import_react32.useCallback((result2)=>{setShowTeamCreate(!1),runTeamCreation(result2,workspaceRoot),pendingTeamNameRef.current=result2.teamName},[workspaceRoot]),handleTeamCreateCancel=import_react32.useCallback(()=>{setShowTeamCreate(!1)},[]);return import_react32.useEffect(()=>{let pending=pendingTeamNameRef.current;if(!pending||!diagnostics)return;let session=diagnostics.sessions.find((s2)=>s2.name===pending);if(!session)return;pendingTeamNameRef.current=null,onTmuxSessionSelect(session.name,resolvePreferredWindowIndex(session,pending))},[diagnostics,onTmuxSessionSelect]),{showTeamCreate,handleOpenTeamCreate,handleTeamCreateConfirm,handleTeamCreateCancel}}function handleEnterAgent(node,onTmuxSessionSelect,spawn5=spawnAgent){if(node.wsAgentState!=="running"&&node.wsAgentState!=="spawning")spawn5(agentNameFromNode(node),onTmuxSessionSelect);else if(node.wsAgentState==="running"){let target=getSessionTarget(node);if(target)onTmuxSessionSelect(target.sessionName,target.windowIndex)}}function dispatchContextMenuAction(action,node,payload,deps){let name=node.label;if(action==="spawn-into"&&node.type==="agent"&&deps.openSpawnInto){deps.openSpawnInto(agentNameFromNode(node));return}if(handleAttachAction(action,node,deps.onTmuxSessionSelect))return;if(handleRetryAction(action,name,deps.onTmuxSessionSelect))return;if(handleGenieAction(action,name,payload))return;let tmuxServer=process.env.GENIE_TMUX_SERVER||"genie";if(handleRenameAction(action,node,tmuxServer,payload))return;if(handleAgentWindowActions(action,node,name,tmuxServer,deps.onNewAgentWindow))return;if(handleSessionNodeActions(action,node,tmuxServer,payload))return;if(handleWindowNodeActions(action,node,deps.sessionTree,tmuxServer,payload))return;handlePaneNodeActions(action,node,deps.sessionTree,tmuxServer,deps.onNewAgentWindow)}function handleAttachAction(action,node,onTmuxSessionSelect){if(action!=="attach")return!1;let target=getSessionTarget(node);if(target)onTmuxSessionSelect(target.sessionName,target.windowIndex);return!0}function handleRetryAction(action,name,onTmuxSessionSelect){if(action!=="retry")return!1;return(async()=>{try{let{reconcileStaleSpawns:reconcileStaleSpawns2}=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry));await reconcileStaleSpawns2()}catch{}spawnAgent(name,onTmuxSessionSelect)})(),!0}function handleGenieAction(action,name,payload){if(action==="send"&&payload)return executeGenie(["agent","send",payload,"--to",name]),!0;if(action==="answer-text"&&payload)return executeGenie(["agent","answer",name,`text:${payload}`]),!0;let genieArgs={spawn:["spawn",name],"spawn-plan":["spawn",name,"--plan-mode"],stop:["agent","stop",name],kill:["agent","kill",name],log:["agent","log",name],show:["agent","show",name],read:["read",name],"answer-yes":["agent","answer",name,"yes"],"answer-no":["agent","answer",name,"no"]}[action];if(genieArgs)return executeGenie(genieArgs),!0;return!1}function handleRenameAction(action,node,tmuxServer,payload){if(action==="rename-session"&&payload){let sess=node.type==="agent"?node.data.sessionName||node.label:node.id.split(":").slice(1).join(":");return executeTmux3(["-L",tmuxServer,"rename-session","-t",sess,payload]),!0}if(action==="rename-window"&&payload){let idParts=node.id.split(":"),windowTarget=`${idParts[1]}:${idParts[2]}`;return executeTmux3(["-L",tmuxServer,"rename-window","-t",windowTarget,payload]),!0}if(action==="rename-pane"&&payload&&node.type==="pane"){let paneId=node.data.paneId;return executeTmux3(["-L",tmuxServer,"select-pane","-t",`${paneId}`,"-T",payload]),!0}return!1}function handleAgentWindowActions(action,node,name,tmuxServer,onNewAgentWindow){if(action==="agent-new-window"&&node.type==="agent"){if(onNewAgentWindow)onNewAgentWindow(agentNameFromNode(node));return!0}if(action==="new-empty-window"&&node.type==="agent"){let sessionName=node.data.sessionName||name;return executeTmux3(["-L",tmuxServer,"new-window","-a","-t",sessionName]),!0}return!1}function handleSessionNodeActions(action,node,tmuxServer,payload){if(node.type!=="session")return!1;let sess=node.id.split(":").slice(1).join(":");if(action==="kill-session")return executeTmux3(["-L",tmuxServer,"kill-session","-t",sess]),!0;if(action==="new-window")return executeTmux3(["-L",tmuxServer,"new-window","-a","-t",sess]),!0;if(action==="clone-session")return executeTmux3(["-L",tmuxServer,"new-session","-d","-s",`${sess}-clone`,"-t",sess]),!0;if(action==="spawn-in-session"&&payload)return executeGenie(["spawn",payload,"--session",sess]),!0;return!1}function handleWindowNodeActions(action,node,sessionTree,tmuxServer,payload){if(node.type!=="window")return!1;let idParts=node.id.split(":"),windowTarget=`${idParts[1]}:${idParts[2]}`;if(action==="kill-window")return executeTmux3(["-L",tmuxServer,"kill-window","-t",windowTarget]),!0;if(action==="window-new-agent"){let parentAgent=findParentAgent(sessionTree,node.id);if(parentAgent){let agentFullName=agentNameFromNode(parentAgent),suffix2=Date.now()%1e4,role=`${agentFullName}-${suffix2}`;executeGenie(["spawn",agentFullName,"--role",role,"--window",windowTarget])}return!0}if(action==="split-pane")return executeTmux3(["-L",tmuxServer,"split-window","-t",windowTarget]),!0;if(action==="spawn-in-window"&&payload)return executeGenie(["spawn",payload,"--session",idParts[1]]),!0;return!1}function handlePaneNodeActions(action,node,sessionTree,tmuxServer,onNewAgentWindow){if(node.type!=="pane")return!1;let paneId=node.data.paneId;if(action==="clone-agent"){let parentAgent=findParentAgent(sessionTree,node.id);if(parentAgent&&onNewAgentWindow)onNewAgentWindow(agentNameFromNode(parentAgent));return!0}if(action==="kill-pane")return executeTmux3(["-L",tmuxServer,"kill-pane","-t",`${paneId}`]),!0;if(action==="split-h")return executeTmux3(["-L",tmuxServer,"split-window","-h","-t",`${paneId}`]),!0;if(action==="split-v")return executeTmux3(["-L",tmuxServer,"split-window","-v","-t",`${paneId}`]),!0;return!1}function buildFooterHint(workspaceRoot){return`\u2191\u2193:nav \u2190\u2192:expand Enter:${workspaceRoot?"spawn/attach":"attach"} ^T:new${workspaceRoot?" ^N:team":""} R:retry .:menu`}function tryOpenTeamCreate(key,opts){if(!key.ctrl||key.name!=="n")return!1;if(!opts.workspaceRoot||opts.showTeamCreate||opts.contextMenuNodeId)return!1;return opts.handleOpenTeamCreate(),!0}function tryOpenContextMenu(flatNodes,selectedIndex,setContextMenuNodeId){let node=flatNodes[selectedIndex]?.node;if(node&&buildMenuItems(node).length>0)return setContextMenuNodeId(node.id),!0;return!1}function dispatchNavKey(key,handlers,agentAction){let n=key.name;if(n==="up"||n==="k"||n==="down"||n==="j")handlers.handleVerticalNav(n);else if(n==="right"||n==="l"||n==="left"||n==="h")handlers.handleExpandCollapse(n);else if(n==="enter"||n==="return")handlers.handleEnter();else if(n==="r")handlers.handleRetry();else if(key.ctrl&&n==="t")agentAction()}function handleKeyboardInput(key,opts){if(key.name==="."&&!opts.contextMenuNodeId){if(tryOpenContextMenu(opts.flatNodes,opts.selectedIndex,opts.setContextMenuNodeId))return}if(opts.contextMenuNodeId)return;dispatchNavKey(key,opts,()=>{let node=opts.flatNodes[opts.selectedIndex]?.node;if(node?.type==="agent"&&node.wsAgentState==="running"&&opts.onNewAgentWindow)opts.onNewAgentWindow(agentNameFromNode(node))})}function agentNameFromNode(node){return node.id.replace(/^agent:/,"")}function spawnAgent(name,onTmuxSessionSelect){try{let{spawn:spawn5}=__require("child_process"),{join:join94,resolve:resolve23}=__require("path"),{existsSync:existsSync77,mkdirSync:mkdirSync35,openSync:openSync6}=__require("fs"),{homedir:homedir52}=__require("os"),bunPath=process.execPath||"bun",genieBin=process.argv[1],wsRoot=process.env.GENIE_TUI_WORKSPACE,sessionName=name.replace(/\//g,"-"),cwd;if(wsRoot){let parentName=name.includes("/")?name.slice(0,name.indexOf("/")):name,agentDir=resolve23(join94(wsRoot,"agents",parentName));if(existsSync77(agentDir))cwd=agentDir}let{GENIE_TUI_PANE:_a,GENIE_TUI_RIGHT:_b,GENIE_TUI_WORKSPACE:_c,GENIE_TUI_TEAM:_d,GENIE_IS_DAEMON:_e2,...cleanEnv}=process.env,logDir=join94(homedir52(),".genie","logs","tui-spawn");try{mkdirSync35(logDir,{recursive:!0})}catch{}let logPath=join94(logDir,`${sessionName}-${Date.now()}.log`),logFd;try{logFd=openSync6(logPath,"a")}catch{logFd=void 0}let spawnOpts=logFd!==void 0?{detached:!0,stdio:["ignore",logFd,logFd],cwd,env:cleanEnv}:{detached:!0,stdio:"ignore",cwd,env:cleanEnv},child=genieBin&&genieBin!=="genie"?spawn5(bunPath,[genieBin,"spawn",name,"--session",sessionName,"--new-window"],spawnOpts):spawn5("genie",["spawn",name,"--session",sessionName,"--new-window"],spawnOpts);if(child.on("exit",(code)=>{if(code&&code!==0)console.error(`TUI: spawn "${name}" exited ${code}. See ${logPath}`)}),child.on("error",(err)=>{console.error(`TUI: spawn "${name}" error: ${err.message}. See ${logPath}`)}),child.unref(),onTmuxSessionSelect)attachSpawnedAgentWhenReady(sessionName,onTmuxSessionSelect)}catch(err){console.error(`TUI: spawn failed for ${name}:`,err instanceof Error?err.message:err)}}function attachSpawnedAgentWhenReady(sessionName,onTmuxSessionSelect,attempt=0){(async()=>{try{let session=(await collectDiagnostics()).sessions.find((candidate)=>candidate.name===sessionName);if(session){let windowIndex=resolvePreferredWindowIndex(session,sessionName);if(windowIndex!==void 0){onTmuxSessionSelect(sessionName,windowIndex);return}}}catch{}if(attempt>=40){onTmuxSessionSelect(sessionName);return}setTimeout(()=>{attachSpawnedAgentWhenReady(sessionName,onTmuxSessionSelect,attempt+1)},250)})()}function executeTmux3(args){try{let{spawn:spawn5}=__require("child_process");spawn5("tmux",args,{detached:!0,stdio:"ignore"}).unref()}catch{}}function executeGenie(args){try{let{spawn:spawn5}=__require("child_process"),bunPath=process.execPath||"bun",genieBin=process.argv[1];(genieBin&&genieBin!=="genie"?spawn5(bunPath,[genieBin,...args],{detached:!0,stdio:"ignore"}):spawn5("genie",args,{detached:!0,stdio:"ignore"})).unref()}catch{}}function executeGenieAwaited(args){return new Promise((resolve23,reject)=>{try{let{spawn:spawn5}=__require("child_process"),bunPath=process.execPath||"bun",genieBin=process.argv[1],child=genieBin&&genieBin!=="genie"?spawn5(bunPath,[genieBin,...args],{stdio:"ignore"}):spawn5("genie",args,{stdio:"ignore"});child.on("exit",(code)=>resolve23(code)),child.on("error",reject)}catch(err){reject(err instanceof Error?err:Error(String(err)))}})}function resolveSpawnHereTarget(node){if(node.type==="session"){let sess=node.id.split(":").slice(1).join(":");if(sess.length===0)return null;return{session:sess}}if(node.type==="window"){let idParts=node.id.split(":");if(idParts.length<3)return null;return{session:idParts[1],window:`${idParts[1]}:${idParts[2]}`}}return null}function executeSpawnIntent(intent){try{let{argv}=buildSpawnInvocation(intent);executeGenie(argv)}catch(err){console.error("TUI: spawn-intent execution failed:",err instanceof Error?err.message:err)}}async function runTeamCreation(result2,workspaceRoot){let argv;try{({argv}=buildSpawnInvocation({kind:"create-team",name:result2.teamName,repo:workspaceRoot}))}catch(err){console.error("TUI: team create intent build failed:",err instanceof Error?err.message:err);return}let createExit=null;try{createExit=await executeGenieAwaited(argv)}catch(err){console.error("TUI: team create spawn failed:",err instanceof Error?err.message:err);return}if(createExit!==0){console.error(`TUI: team create exited ${createExit} \u2014 skipping member hires for "${result2.teamName}"`);return}for(let member of result2.members)try{let code=await executeGenieAwaited(["team","hire",member,"--team",result2.teamName]);if(code!==0)console.error(`TUI: team hire "${member}" exited ${code} \u2014 continuing with remaining members`)}catch(err){console.error(`TUI: team hire "${member}" failed:`,err instanceof Error?err.message:err)}}function findParentAgent(tree,targetId){for(let node of tree){if(node.type==="agent"&&containsNode(node,targetId))return node;let found=findParentAgent(node.children,targetId);if(found)return found}return null}function containsNode(node,targetId){if(node.id===targetId)return!0;return node.children.some((c)=>containsNode(c,targetId))}function mergeExpandedState(oldTree,newTree){if(oldTree.length===0)return newTree;let oldState=new Map;function collect(nodes){for(let n of nodes)oldState.set(n.id,{expanded:n.expanded,childCount:n.children.length}),collect(n.children)}collect(oldTree);function apply(nodes){return nodes.map((n)=>({...n,expanded:(()=>{let previous=oldState.get(n.id);if(!previous)return n.expanded;if(previous.childCount===0&&n.children.length>0)return n.expanded;return previous.expanded})(),children:apply(n.children)}))}return apply(newTree)}var import_react32;var init_Nav=__esm(async()=>{init_spawn_invocation();init_workspace();init_diagnostics();init_initial_agent();init_session_tree();init_theme2();init_SystemStats();init_TreeNode();init_jsx_dev_runtime();await __promiseAll([init_react2(),init_AgentPicker(),init_ContextMenu(),init_SpawnTargetPicker(),init_TeamCreate()]);import_react32=__toESM(require_react_development(),1)});function QuitDialog({onConfirm,onCancel}){return useKeyboard((key)=>{if(key.name==="enter"||key.name==="return"||key.name==="y")onConfirm();else if(key.name==="escape"||key.name==="n")onCancel()}),import_jsx_dev_runtime2.jsxDEV("box",{position:"absolute",width:"100%",height:"100%",justifyContent:"center",alignItems:"center",backgroundColor:palette.bgOverlay,children:import_jsx_dev_runtime2.jsxDEV("box",{border:!0,borderColor:palette.borderActive,backgroundColor:palette.bgRaised,paddingX:3,paddingY:1,flexDirection:"column",alignItems:"center",gap:1,children:[import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.accent,children:"Close TUI?"},void 0,!1,void 0,this)},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("text",{children:[import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.text,children:"Enter"},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:" to close "},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:" | "},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.text,children:" Esc"},void 0,!1,void 0,this),import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:" to cancel"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),import_jsx_dev_runtime2.jsxDEV("text",{children:import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textMuted,children:"Daemon keeps running. `genie serve stop` to shut down."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var init_QuitDialog=__esm(async()=>{init_theme2();init_jsx_dev_runtime();await init_react2()});import{execSync as execSync18}from"child_process";function App({rightPane,workspaceRoot,initialAgent}){let renderer=useRenderer(),[showQuit,setShowQuit]=import_react36.useState(!1),[showHelp,setShowHelp]=import_react36.useState(!1),[activeSession,setActiveSession]=import_react36.useState(null);import_react36.useEffect(()=>{let title=activeSession?`${BASE_TERMINAL_TITLE} \u2014 ${activeSession}`:BASE_TERMINAL_TITLE;try{renderer.setTerminalTitle(title)}catch{}},[renderer,activeSession]);let handleQuit=import_react36.useCallback(()=>{try{execSync18("tmux -L genie-tui kill-server",{stdio:"ignore"})}catch{}},[]);useBindings(()=>({commands:[{name:"app.quit",title:"Close TUI",desc:"Close TUI window (daemon keeps running \u2014 use `genie serve stop` to shut down)",category:"app",run(){if(showQuit)handleQuit();else setShowQuit(!0)}},{name:"app.help.toggle",title:"Toggle help overlay",desc:"Show/hide the keyboard shortcut overlay",category:"app",run(){setShowHelp((prev)=>!prev)}},{name:"app.console.toggle",title:"Toggle console overlay",desc:"Show/hide the OpenTUI console (logs)",category:"app",run(){renderer.console.toggle()}}],bindings:[{key:"ctrl+q",cmd:"app.quit"},{key:"f1",cmd:"app.help.toggle"},{key:"`",cmd:"app.console.toggle"}]}),[renderer,showQuit,handleQuit]);let handleTmuxSessionSelect=import_react36.useCallback((sessionName,windowIndex)=>{if(setActiveSession(sessionName),!rightPane)return;attachProjectWindow(rightPane,sessionName,windowIndex)},[rightPane]);return import_jsx_dev_runtime2.jsxDEV("box",{width:"100%",height:"100%",children:[import_jsx_dev_runtime2.jsxDEV(Nav,{onTmuxSessionSelect:handleTmuxSessionSelect,onNewAgentWindow:newAgentWindow,workspaceRoot,initialAgent,keyboardDisabled:showQuit||showHelp},void 0,!1,void 0,this),showHelp?import_jsx_dev_runtime2.jsxDEV(HelpOverlay,{onClose:()=>setShowHelp(!1)},void 0,!1,void 0,this):null,showQuit?import_jsx_dev_runtime2.jsxDEV(QuitDialog,{onConfirm:handleQuit,onCancel:()=>setShowQuit(!1)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var import_react36,BASE_TERMINAL_TITLE="genie tui";var init_app=__esm(async()=>{init_react();init_tmux2();init_jsx_dev_runtime();await __promiseAll([init_react2(),init_HelpOverlay(),init_Nav(),init_QuitDialog()]);import_react36=__toESM(require_react_development(),1)});function normalizeBindingTokenName(token){let normalized=token.trim().toLowerCase();if(!normalized)throw Error("Invalid keymap token: token cannot be empty");return normalized}function normalizeKeyName(name){let normalized=name.trim().toLowerCase();if(!normalized)throw Error("Invalid key name: key name cannot be empty");return normalized}function normalizeKeyStroke(input){return{name:normalizeKeyName(input.name),ctrl:input.ctrl??!1,shift:input.shift??!1,meta:input.meta??!1,super:input.super??!1,hyper:input.hyper||void 0}}function cloneKeyStroke(stroke){return{name:stroke.name,ctrl:stroke.ctrl,shift:stroke.shift,meta:stroke.meta,super:stroke.super,hyper:stroke.hyper||void 0}}function createKeySequencePart(input,options){let stroke=cloneKeyStroke(normalizeKeyStroke(input));return{stroke,display:options?.display??stringifyCanonicalStroke(stroke),match:options?.match??createKeyMatch(stroke),tokenName:options?.tokenName?normalizeBindingTokenName(options.tokenName):void 0}}function cloneKeySequencePart(part){return{stroke:cloneKeyStroke(part.stroke),display:part.display,match:part.match,tokenName:part.tokenName,patternName:part.patternName,payloadKey:part.payloadKey}}function cloneKeySequence(parts){return parts.map((part)=>cloneKeySequencePart(part))}function resolveKeyMatch(input){if("match"in input)return input.match;if("stroke"in input)return createKeyMatch(input.stroke);return createKeyMatch(input)}function createKeyMatch(input){return`key:${buildKeyMatchId(normalizeKeyStroke(input))}`}function createTextKeyMatch(id){let normalized=id.trim();if(!normalized)throw Error("Invalid keymap match id: id cannot be empty");return`text:${normalized}`}function stringifyKeyStroke(input,options){if("stroke"in input){if(options?.preferDisplay&&input.display)return input.display;return stringifyCanonicalStroke(input.stroke)}return stringifyCanonicalStroke(normalizeKeyStroke(input))}function stringifyKeySequence(input,options){return input.map((part)=>stringifyKeyStroke(part,options)).join(options?.separator??"")}function stringifyCanonicalStroke(stroke){let parts=[];if(stroke.ctrl)parts.push("ctrl");if(stroke.shift)parts.push("shift");if(stroke.meta)parts.push("meta");if(stroke.super)parts.push("super");if(stroke.hyper)parts.push("hyper");return parts.push(stroke.name==="return"?"enter":stroke.name),parts.join("+")}function buildKeyMatchId(stroke){return`${stroke.name}:${stroke.ctrl?1:0}:${stroke.shift?1:0}:${stroke.meta?1:0}:${stroke.super?1:0}:${stroke.hyper?1:0}`}function getFocusedTargetIfAvailable(host){if(host.isDestroyed)return null;return host.getFocusedTarget()}function forEachActivationTarget(host,focused,visit){let current=focused??host.rootTarget,isFocusedTarget=focused!==null;while(current){if(visit(current,isFocusedTarget)===!1)return;current=host.getParentTarget(current),isFocusedTarget=!1}}function getActivationPath(host,focused){let path6=new Set;return forEachActivationTarget(host,focused,(current)=>{path6.add(current)}),path6}function getActiveLayersForFocused(layers,host,focused){let activeLayers=[],activationPath=getActivationPath(host,focused),sortedLayers=Array.isArray(layers)?layers:getSortedLayers(layers);for(let layer of sortedLayers)if(isLayerActiveForFocused(host,layer,focused,activationPath))activeLayers.push(layer);return activeLayers}function getSortedLayers(layers){return[...layers].sort((left,right)=>{return right.priority-left.priority||right.order-left.order})}function isLayerActiveForFocused(host,layer,focused,activationPath=getActivationPath(host,focused)){let target=layer.target;if(!target)return!0;if(host.isTargetDestroyed(target))return!1;if(layer.targetMode==="focus")return target===focused;return activationPath.has(target)}function patternCaptureCount(capture2){let part=capture2.binding.sequence[capture2.index];if(!part?.patternName)return 0;let captured=capture2.patterns?.at(-1);return captured?.name===part.patternName?captured.values.length:0}function captureHasMinimum(capture2,patterns2,missingPatternResult=!0){let part=capture2.binding.sequence[capture2.index];if(!part?.patternName)return!0;let pattern=patterns2.get(part.patternName);return pattern?patternCaptureCount(capture2)>=pattern.min:missingPatternResult}function captureHasContinuations(capture2,patterns2,missingPatternMinimum=!0){let part=capture2.binding.sequence[capture2.index];if(part?.patternName){let pattern=patterns2.get(part.patternName);if(pattern&&patternCaptureCount(capture2)<pattern.max)return!0}return captureHasMinimum(capture2,patterns2,missingPatternMinimum)&&capture2.index+1<capture2.binding.sequence.length}function captureIsExact(capture2,patterns2){return capture2.index===capture2.binding.sequence.length-1&&captureHasMinimum(capture2,patterns2,!1)}function createSequenceNode(parent,stroke,match,pattern){return{parent,depth:parent?parent.depth+1:0,stroke,match,pattern,children:new Map,patternChildren:[],bindings:[],reachableBindings:[]}}function buildSequenceTree(bindings,patterns2){let root=createSequenceNode(null,null,null);for(let binding of bindings){if(binding.event!=="press")continue;let node=root;for(let part of binding.sequence){let child;if(part.patternName){let pattern=patterns2.get(part.patternName);if(child=node.patternChildren.find((candidate)=>candidate.pattern?.name===part.patternName),!child)child=createSequenceNode(node,part.stroke,part.match,pattern),node.patternChildren.push(child)}else if(child=node.children.get(part.match),!child)child=createSequenceNode(node,part.stroke,part.match),node.children.set(part.match,child);child.reachableBindings.push(binding),node=child}node.bindings.push(binding)}return root}function activeOptionsForCaptures(captures,patterns2){let options=[];for(let capture2 of captures){if(!captureHasMinimum(capture2,patterns2))continue;let index=capture2.index+1,part=capture2.binding.sequence[index];if(part)options.push({part,binding:capture2.binding,index,exact:index===capture2.binding.sequence.length-1,continues:index<capture2.binding.sequence.length-1})}return options}function appendPatternCapture(capture2,index,part,value){let patternName=part.patternName;if(!patternName)return{...capture2,index};let patterns2=[...capture2.patterns??[]],last=patterns2.at(-1);if(last?.name===patternName)patterns2[patterns2.length-1]={...last,values:[...last.values,value],parts:[...last.parts,part]};else patterns2.push({name:patternName,payloadKey:part.payloadKey??patternName,values:[value],parts:[part]});return{layer:capture2.layer,binding:capture2.binding,index,parts:[...capture2.parts,part],patterns:patterns2}}function capturePriority(capture2,matchKeys){let part=capture2.parts.at(-1);if(!part||part.patternName)return matchKeys.length;let index=matchKeys.indexOf(part.match);return index===-1?matchKeys.length:index}function advanceSequenceBinding(layer,binding,index,parts,patterns2,matchKeys,event,matchPattern,createPatternPart){let part=binding.sequence[index];if(!part)return;if(part.patternName){let patternMatch=matchPattern(part.patternName,event);if(!patternMatch)return;let eventPart=createPatternPart(event,part.patternName,patternMatch);return appendPatternCapture({layer,binding,index,parts,patterns:patterns2},index,eventPart,patternMatch.value??event.name)}if(!matchKeys.includes(part.match))return;return{layer,binding,index,parts:[...parts,part],patterns:patterns2}}function advanceSequenceCapture(capture2,matchKeys,event,patterns2,matchPattern,createPatternPart){let currentPart=capture2.binding.sequence[capture2.index];if(currentPart?.patternName){let pattern=patterns2.get(currentPart.patternName);if(pattern&&patternCaptureCount(capture2)<pattern.max){let patternMatch=matchPattern(pattern.name,event);if(patternMatch){let part=createPatternPart(event,pattern.name,patternMatch);return appendPatternCapture(capture2,capture2.index,part,patternMatch.value??event.name)}}if(!captureHasMinimum(capture2,patterns2,!1))return;return advanceSequenceBinding(capture2.layer,capture2.binding,capture2.index+1,capture2.parts,capture2.patterns,matchKeys,event,matchPattern,createPatternPart)}return advanceSequenceBinding(capture2.layer,capture2.binding,capture2.index+1,capture2.parts,capture2.patterns,matchKeys,event,matchPattern,createPatternPart)}function collectRootSequenceCaptures(layer,matchKeys,event,matchPattern,createPatternPart){let captures=[],bestPriority=Number.POSITIVE_INFINITY;for(let binding of layer.bindings){if(binding.event!=="press")continue;let capture2=advanceSequenceBinding(layer,binding,0,[],void 0,matchKeys,event,matchPattern,createPatternPart);if(!capture2)continue;let priority=capturePriority(capture2,matchKeys);if(priority<bestPriority)bestPriority=priority,captures.length=0;if(priority===bestPriority)captures.push(capture2)}return captures}var KEYMAP_EXTENSION_CONTEXT;var init_index_frk6sdcd=__esm(()=>{KEYMAP_EXTENSION_CONTEXT=Symbol("keymap-extension-context")});function createRuntimeEmitter(onError){let listeners2=Object.create(null),off=(name,listener)=>{let current=listeners2[name];if(!current)return;let next=current.filter((candidate)=>candidate!==listener);if(next.length===0)delete listeners2[name];else if(next.length!==current.length)listeners2[name]=next};return{hook(name,listener){return listeners2[name]=[...listeners2[name]??[],listener],()=>off(name,listener)},has(name){return(listeners2[name]?.length??0)>0},emit(name,...args){let current=listeners2[name];if(!current)return;for(let listener of current)try{if(args.length===0)listener();else listener(args[0])}catch(error2){onError(name,error2)}}}}function createItems(){let items=[];return{get:()=>items,set:(next)=>{items=next},remove(value){items=items.filter((candidate)=>candidate!==value)},has:()=>items.length>0,clear:()=>{items=[]}}}function createRuntimeOrderedRegistry(){let items=createItems();return{append(value){return items.set([...items.get(),value]),()=>items.remove(value)},prepend(value){return items.set([value,...items.get()]),()=>items.remove(value)},values:items.get,has:items.has,clear:items.clear}}function createRuntimePriorityRegistry(){let items=createItems(),order=0;return{register(listener,options){let registered={...options,listener,order:order++};return items.set([...items.get(),registered].sort((left,right)=>{return right.priority-left.priority||left.order-right.order})),()=>items.remove(registered)},entries:items.get,has:items.has,clear:items.clear}}function isKeyLike(value){return typeof value==="string"||!!value&&typeof value==="object"&&!Array.isArray(value)}function validateBindings(bindings){if(!Array.isArray(bindings))return{ok:!1,reason:"Invalid keymap bindings: expected an array of binding objects"};for(let[index,binding]of bindings.entries()){if(!binding||typeof binding!=="object"||Array.isArray(binding))return{ok:!1,reason:`Invalid keymap binding at index ${index}: expected a binding object`};if(!isKeyLike(binding.key))return{ok:!1,reason:`Invalid keymap binding at index ${index}: expected "key" to be a string or keystroke object`}}return{ok:!0}}function snapshotBindings(bindings){let validation=validateBindings(bindings);if(!validation.ok)throw Error(validation.reason);return bindings.map((binding)=>({...binding,key:typeof binding.key==="string"?binding.key:{...binding.key}}))}function snapshotParsedBinding(binding){return{...binding,sequence:cloneKeySequence(binding.sequence)}}function createLayerDiagnostics(notify,commands){let analyzers=createRuntimeOrderedRegistry();return{prependLayerAnalyzer(analyzer){return analyzers.prepend(analyzer)},appendLayerAnalyzer(analyzer){return analyzers.append(analyzer)},clearLayerAnalyzers(){analyzers.clear()},analyzeLayer(options){let registeredAnalyzers=analyzers.values();if(registeredAnalyzers.length===0)return;let bindings=buildLayerBindingAnalyses(options.bindings),ctx={target:options.target,order:options.order,sourceBindings:options.sourceBindings,bindings,hasTokenBindings:options.hasTokenBindings,checkCommandResolution(command){return commands.getCommandResolutionStatus(command,options.commands)},warn(code,warning,message){notify.emitWarning(code,warning,message)},warnOnce(key,code,warning,message){notify.warnOnce(key,code,warning,message)},error(code,error2,message){notify.emitError(code,error2,message)}};for(let analyzer of registeredAnalyzers)try{analyzer(ctx)}catch(error2){notify.emitError("layer-analyzer-error",error2,"[Keymap] Error in layer analyzer:")}}}}function buildLayerBindingAnalyses(bindings){return bindings.map((binding)=>({sequence:cloneKeySequence(binding.sequence),command:binding.command,attrs:binding.attrs,event:binding.event,preventDefault:binding.preventDefault,fallthrough:binding.fallthrough,parsedBinding:snapshotParsedBinding(binding.parsedBinding),sourceTarget:binding.sourceTarget,sourceLayerOrder:binding.sourceLayerOrder,bindingIndex:binding.bindingIndex,hasCommandAtSequence:bindings.some((candidate)=>{return candidate.event==="press"&&candidate.command!==void 0&&sameSequence(candidate,binding)}),hasContinuations:bindings.some((candidate)=>{return candidate.event==="press"&&isPrefix(binding,candidate)})}))}function sameSequence(left,right){return left.sequence.length===right.sequence.length&&left.sequence.every((part,index)=>part.match===right.sequence[index]?.match)}function isPrefix(left,right){return left.sequence.length<right.sequence.length&&left.sequence.every((part,index)=>part.match===right.sequence[index]?.match)}function createActiveKeysCache(){return{version:-1,notifyVersion:-1,focused:void 0,value:[],targets:new WeakMap}}function createActiveKeysCaches(){return{plain:createActiveKeysCache(),bindings:createActiveKeysCache(),metadata:createActiveKeysCache(),bindingsAndMetadata:createActiveKeysCache()}}function getActiveKeysCache(caches,options){if(options===void 0)return caches.plain;let includeBindings=options.includeBindings===!0,includeMetadata=options.includeMetadata===!0;return includeBindings?includeMetadata?caches.bindingsAndMetadata:caches.bindings:includeMetadata?caches.metadata:caches.plain}function getFocusedActiveKeysCache(cache,cacheVersion,focused){let cached=focused?cache.targets.get(focused):cache.nullTarget;return cached?.version===cacheVersion?cached:void 0}function setFocusedActiveKeysCache(cache,cacheVersion,focused,value){let cached={version:cacheVersion,value};if(focused)cache.targets.set(focused,cached);else cache.nullTarget=cached}function isSamePendingSequence(current,next){if(current===next)return!0;if(!current||!next)return!1;if(current.captures.length!==next.captures.length)return!1;for(let index=0;index<current.captures.length;index+=1){let left=current.captures[index],right=next.captures[index];if(!left||!right||left.layer!==right.layer||left.binding!==right.binding||left.index!==right.index||left.parts.length!==right.parts.length)return!1;for(let partIndex=0;partIndex<left.parts.length;partIndex+=1)if(left.parts[partIndex]?.match!==right.parts[partIndex]?.match)return!1;let leftPatterns=left.patterns??[],rightPatterns=right.patterns??[];if(leftPatterns.length!==rightPatterns.length)return!1;for(let patternIndex=0;patternIndex<leftPatterns.length;patternIndex+=1){let leftPattern=leftPatterns[patternIndex],rightPattern=rightPatterns[patternIndex];if(!leftPattern||!rightPattern||leftPattern.name!==rightPattern.name)return!1;if(leftPattern.values.length!==rightPattern.values.length)return!1;for(let valueIndex=0;valueIndex<leftPattern.values.length;valueIndex+=1)if(!Object.is(leftPattern.values[valueIndex],rightPattern.values[valueIndex]))return!1}}return!0}function popCapture(capture2){let lastPart=capture2.parts.at(-1);if(!lastPart||capture2.parts.length<=1)return;let index=capture2.index-1,patterns2=capture2.patterns;if(lastPart.patternName){let lastPattern=patterns2?.at(-1);if(lastPattern?.name===lastPart.patternName)if(lastPattern.values.length>1)index=capture2.index,patterns2=[...(patterns2??[]).slice(0,-1),{...lastPattern,values:lastPattern.values.slice(0,-1),parts:lastPattern.parts.slice(0,-1)}];else patterns2=(patterns2??[]).slice(0,-1)}return{layer:capture2.layer,binding:capture2.binding,index,parts:capture2.parts.slice(0,-1),patterns:patterns2}}function collectSequencePartsFromPending(pending){let firstCapture=pending.captures[0];if(!firstCapture||firstCapture.parts.length===0)return[];let parts=[];for(let index=0;index<firstCapture.parts.length;index+=1){let firstPart=firstCapture.parts[index];if(!firstPart)continue;let display,tokenName,hasDisplayConflict=!1,hasTokenConflict=!1;for(let capture2 of pending.captures){let part=capture2.parts[index];if(!part)continue;if(display===void 0){display=part.display,tokenName=part.tokenName;continue}if(!hasDisplayConflict&&display!==part.display)hasDisplayConflict=!0;if(!hasTokenConflict&&tokenName!==part.tokenName)hasTokenConflict=!0}if(display===void 0||hasDisplayConflict)display=stringifyKeyStroke(firstPart.stroke);if(hasTokenConflict)tokenName=void 0;parts.push(createKeySequencePart(firstPart.stroke,{display,match:firstPart.match,tokenName}))}return parts}function getLiveHost(host){if(host.isDestroyed)throw Error("Cannot use a keymap after its host was destroyed");return host}function createActivationService(state,host,hooks,notify,conditions,catalog,options={}){let activeKeysCaches=createActiveKeysCaches(),pendingSequenceCacheVersion=-1,pendingSequenceCache=[],getFocusedTarget=()=>{return getLiveHost(host).getFocusedTarget()},getFocusedTargetIfAvailable2=()=>{return getFocusedTargetIfAvailable(host)},setPendingSequence=(next)=>{let previous=state.pending;if(isSamePendingSequence(previous,next))return;state.pending=next,options.onPendingSequenceChanged?.(previous,next),notifyPendingSequenceChange(),notify.queueStateChange()},ensureValidPendingSequence=()=>{let pending=state.pending;if(!pending)return;let focused=getFocusedTarget(),activeView=catalog.getActiveCommandView(focused),captures=pending.captures.filter((capture2)=>{return state.layers.has(capture2.layer)&&isActiveLayerForFocused(capture2.layer,focused)&&conditions.matchesConditions(capture2.layer)&&bindingMatchesRuntimeState(capture2.binding,focused,activeView)&&captureHasContinuations(capture2,state.patterns)});if(captures.length===0){setPendingSequence(null);return}if(captures.length!==pending.captures.length)setPendingSequence({captures});return state.pending??void 0},revalidatePendingSequenceIfNeeded=()=>{if(host.isDestroyed||!state.pending)return;ensureValidPendingSequence()},hasPendingSequenceState=()=>{return!host.isDestroyed&&state.pending!==null},getPendingSequence=()=>{if(pendingSequenceCacheVersion===state.cacheVersion)return pendingSequenceCache;let pending=ensureValidPendingSequence(),sequence=pending?collectSequencePartsFromPending(pending):[];if(!pending||allRegisteredLayersCanCacheActiveKeys())pendingSequenceCacheVersion=state.cacheVersion,pendingSequenceCache=sequence;return sequence},popPendingSequence=()=>{let pending=ensureValidPendingSequence();if(!pending)return!1;let firstCapture=pending.captures[0];if(!firstCapture||firstCapture.parts.length<=1)return setPendingSequence(null),!0;let nextCaptures=[];for(let capture2 of pending.captures){let nextCapture=popCapture(capture2);if(!nextCapture)continue;nextCaptures.push(nextCapture)}if(nextCaptures.length===0)return setPendingSequence(null),!0;return setPendingSequence({captures:nextCaptures}),!0},getActiveKeys=(options2)=>{let includeBindings=options2?.includeBindings===!0,includeMetadata=options2?.includeMetadata===!0,cache=getActiveKeysCache(activeKeysCaches,options2);if(cache.notifyVersion===state.derivedVersion)return cache.value;return collectActiveKeysForCache(cache,includeBindings,includeMetadata)},collectActiveKeysForCache=(cache,includeBindings,includeMetadata)=>{if(host.isDestroyed)getLiveHost(host);let focused=getFocusedTarget(),cached=getFocusedActiveKeysCache(cache,state.cacheVersion,focused);if(cached)return cache.notifyVersion=state.derivedVersion,cache.version=state.cacheVersion,cache.focused=focused,cache.value=cached.value,cached.value;let activeView=catalog.getActiveCommandView(focused),pending=ensureValidPendingSequence(),activeLayers=pending?[]:getActiveLayers(focused),activeKeys=pending?collectActiveKeysFromPending(pending.captures,includeBindings,includeMetadata,focused,activeView):collectActiveKeysAtRoot(activeLayers,includeBindings,includeMetadata,focused,activeView);if(pending?allRegisteredLayersCanCacheActiveKeys():activeLayersCanCacheActiveKeys(activeLayers))cache.version=state.cacheVersion,cache.notifyVersion=state.derivedVersion,cache.focused=focused,cache.value=activeKeys,setFocusedActiveKeysCache(cache,state.cacheVersion,focused,activeKeys);return activeKeys},getActiveKeysForCaptures=(captures,options2)=>{let includeBindings=options2?.includeBindings===!0,includeMetadata=options2?.includeMetadata===!0,focused=getFocusedTarget(),activeView=catalog.getActiveCommandView(focused);return collectActiveKeysFromPending(captures,includeBindings,includeMetadata,focused,activeView)},getActiveKeysForFocused=(focused,options2)=>{let includeBindings=options2?.includeBindings===!0,includeMetadata=options2?.includeMetadata===!0,currentFocused=getFocusedTargetIfAvailable2(),pending=focused===currentFocused?ensureValidPendingSequence():void 0,activeView=catalog.getActiveCommandView(focused);if(pending)return collectActiveKeysFromPending(pending.captures,includeBindings,includeMetadata,focused,activeView);return collectActiveKeysAtRoot(getActiveLayers(focused),includeBindings,includeMetadata,focused,activeView)},getActiveLayers=(focused)=>{if(state.activeLayersCacheVersion===state.cacheVersion&&state.activeLayersCacheFocused===focused)return state.activeLayersCache;return state.activeLayersCacheVersion=state.cacheVersion,state.activeLayersCacheFocused=focused,state.activeLayersCache=getActiveLayersForFocused(state.sortedLayers,host,focused),state.activeLayersCache},isActiveLayerForFocused=(layer,focused)=>{return isLayerActiveForFocused(host,layer,focused)},activeLayersCanCacheActiveKeys=(activeLayers)=>{return!state.commandResolvers.has()&&state.activeKeyCacheBlockers===0},allRegisteredLayersCanCacheActiveKeys=()=>{return!state.commandResolvers.has()&&state.activeKeyCacheBlockers===0},collectMatchingBindings=(bindings,focused,activeView)=>{let matches=[];for(let binding of bindings)if(conditions.matchesConditions(binding)&&catalog.isBindingVisible(binding,focused,activeView))matches.push(binding);return matches},bindingMatchesRuntimeState=(binding,focused,activeView)=>{return conditions.matchesConditions(binding)&&catalog.isBindingVisible(binding,focused,activeView)},getPartPresentation=(bindings,partIndex)=>{let display,tokenName,hasDisplayConflict=!1,hasTokenConflict=!1;for(let binding of bindings){let part=binding.sequence[partIndex];if(!part)continue;if(display===void 0){display=part.display,tokenName=part.tokenName;continue}if(!hasDisplayConflict&&display!==part.display)hasDisplayConflict=!0;if(!hasTokenConflict&&tokenName!==part.tokenName)hasTokenConflict=!0}if(display===void 0||hasDisplayConflict){let stroke=bindings[0]?.sequence[partIndex]?.stroke;display=stroke?stringifyKeyStroke(stroke):""}if(hasTokenConflict)tokenName=void 0;return{display,tokenName}},toActiveBinding=(binding,focused,activeView)=>{return{sequence:binding.sequence,command:binding.command,commandAttrs:catalog.getBindingCommandAttrs(binding,focused,activeView),attrs:binding.attrs,event:binding.event,preventDefault:binding.preventDefault,fallthrough:binding.fallthrough}},collectActiveBindings=(bindings,focused,activeView)=>{return bindings.map((binding)=>toActiveBinding(binding,focused,activeView))},collectActiveKeysAtRoot=(activeLayers,includeBindings,includeMetadata,focused,activeView)=>{let activeKeys=new Map,stopped=new Set;for(let layer of activeLayers){if(layer.root.children.size===0&&layer.root.patternChildren.length===0||!conditions.matchesConditions(layer))continue;collectActiveKeyNodes(layer.root.children.values(),activeKeys,stopped,includeBindings,focused,activeView),collectActiveKeyNodes(layer.root.patternChildren,activeKeys,stopped,includeBindings,focused,activeView)}return materializeActiveKeys(activeKeys,includeBindings,includeMetadata,focused,activeView)},collectActiveKeyNodes=(nodes,activeKeys,stopped,includeBindings,focused,activeView)=>{for(let node of nodes){let bindingKey=node.match;if(!bindingKey||stopped.has(bindingKey)||!node.stroke)continue;let selection=selectActiveKeyNode(node,includeBindings,focused,activeView);if(!selection)continue;let existing=activeKeys.get(bindingKey);if(!existing)activeKeys.set(bindingKey,createActiveKeyState(node.stroke,selection,includeBindings));else updateActiveKeyState(existing,selection,includeBindings);if(selection.stop)stopped.add(bindingKey)}},selectActiveKeyNode=(node,includeBindings,focused,activeView)=>{if(!(node.children.size>0||node.patternChildren.length>0)){let selected2=selectActiveBindings(nodeExactBindingsNeedPrefilter(node)?collectMatchingBindings(node.bindings,focused,activeView):node.bindings,focused,activeView);if(!selected2)return;let presentation2=getPartPresentation(selected2.bindings,node.depth-1);return{display:presentation2.display,tokenName:presentation2.tokenName,continues:!1,firstBinding:selected2.bindings[0],commandBinding:selected2.commandBinding,bindings:includeBindings?[...selected2.bindings]:void 0,stop:selected2.stop}}let reachableBindings=collectMatchingBindings(node.reachableBindings,focused,activeView);if(reachableBindings.length===0)return;let selected=selectActiveBindings(node.bindings,focused,activeView),presentation=getPartPresentation(reachableBindings,node.depth-1);return{display:presentation.display,tokenName:presentation.tokenName,continues:!0,firstBinding:selected?.bindings[0],commandBinding:selected?.commandBinding,bindings:includeBindings&&selected?[...selected.bindings]:void 0,stop:!0}},nodeExactBindingsNeedPrefilter=(node)=>{if(state.commandResolvers.has())return!0;for(let binding of node.bindings)if(binding.matchers.length>0)return!0;return!1},collectActiveKeysFromPending=(captures,includeBindings,includeMetadata,focused,activeView)=>{let activeKeys=new Map,stopped=new Set;return collectActiveKeyOptions(activeOptionsForCaptures(captures,state.patterns),activeKeys,stopped,includeBindings,focused,activeView),materializeActiveKeys(activeKeys,includeBindings,includeMetadata,focused,activeView)},collectActiveKeyOptions=(options2,activeKeys,stopped,includeBindings,focused,activeView)=>{let seen=new Set;for(let option of options2){if(seen.has(option.part.match))continue;seen.add(option.part.match),collectActiveKeyOption(option,options2,activeKeys,stopped,includeBindings,focused,activeView)}},collectActiveKeyOption=(option,siblingOptions,activeKeys,stopped,includeBindings,focused,activeView)=>{let bindingKey=option.part.match;if(stopped.has(bindingKey))return;let selection=selectActiveKeyOption(option,siblingOptions,includeBindings,focused,activeView);if(!selection)return;let existing=activeKeys.get(bindingKey);if(!existing)activeKeys.set(bindingKey,createActiveKeyState(option.part.stroke,selection,includeBindings));else updateActiveKeyState(existing,selection,includeBindings);if(selection.stop)stopped.add(bindingKey)},materializeActiveKeys=(activeKeys,includeBindings,includeMetadata,focused,activeView)=>{let materialized=[];for(let state2 of activeKeys.values()){let activeKey=materializeActiveKey(state2,includeBindings,includeMetadata,focused,activeView);if(activeKey)materialized.push(activeKey)}return materialized},selectActiveKeyOption=(option,siblingOptions,includeBindings,focused,activeView)=>{let matchingOptions=siblingOptions.filter((candidate)=>candidate.part.match===option.part.match),exactBindings=matchingOptions.filter((candidate)=>candidate.exact).map((candidate)=>candidate.binding),selected=selectActiveBindings(exactBindings,focused,activeView),continues=matchingOptions.some((candidate)=>candidate.continues);if(!continues&&!selected)return;let presentation=getOptionPresentation(matchingOptions);return{display:presentation.display,tokenName:presentation.tokenName,continues,firstBinding:selected?.bindings[0],commandBinding:selected?.commandBinding,bindings:includeBindings&&selected?[...selected.bindings]:void 0,stop:continues||selected?.stop===!0}},getOptionPresentation=(options2)=>{let display,tokenName,hasDisplayConflict=!1,hasTokenConflict=!1;for(let option of options2){let part=option.part;if(display===void 0){display=part.display,tokenName=part.tokenName;continue}if(!hasDisplayConflict&&display!==part.display)hasDisplayConflict=!0;if(!hasTokenConflict&&tokenName!==part.tokenName)hasTokenConflict=!0}let firstPart=options2[0]?.part;if(display===void 0||hasDisplayConflict)display=firstPart?stringifyKeyStroke(firstPart.stroke):"";if(hasTokenConflict)tokenName=void 0;return{display,tokenName}},selectActiveBindings=(bindings,focused,activeView)=>{let selected=[],commandBinding;for(let binding of bindings){if(!conditions.matchesConditions(binding)||!catalog.isBindingVisible(binding,focused,activeView))continue;if(selected.push(binding),binding.command===void 0)continue;if(commandBinding??=binding,!binding.fallthrough)return{bindings:selected,commandBinding,stop:!0}}if(selected.length===0)return;return{bindings:selected,commandBinding,stop:!1}},createActiveKeyState=(stroke,selection,includeBindings)=>{return{stroke,display:selection.display,tokenName:selection.tokenName,continues:selection.continues,firstBinding:selection.firstBinding,commandBinding:selection.commandBinding,bindings:includeBindings&&selection.bindings?[...selection.bindings]:void 0}},updateActiveKeyState=(state2,selection,includeBindings)=>{if(!state2.firstBinding&&selection.firstBinding)state2.firstBinding=selection.firstBinding;if(!state2.commandBinding&&selection.commandBinding)state2.commandBinding=selection.commandBinding;if(selection.continues)state2.continues=!0;if(!includeBindings||!selection.bindings||selection.bindings.length===0)return;if(!state2.bindings){state2.bindings=[...selection.bindings];return}state2.bindings.push(...selection.bindings)},materializeActiveKey=(state2,includeBindings,includeMetadata,focused,activeView)=>{if(!state2.commandBinding&&!state2.continues)return;let activeKey={stroke:cloneKeyStroke(state2.stroke),display:state2.display,continues:state2.continues};if(state2.tokenName)activeKey.tokenName=state2.tokenName;if(state2.commandBinding)activeKey.command=state2.commandBinding.command;if(includeBindings&&state2.bindings&&state2.bindings.length>0)activeKey.bindings=state2.bindings.length===1?[toActiveBinding(state2.bindings[0],focused,activeView)]:collectActiveBindings(state2.bindings,focused,activeView);if(includeMetadata){if(state2.firstBinding?.attrs)activeKey.bindingAttrs=state2.firstBinding.attrs;let commandAttrs=state2.commandBinding?catalog.getBindingCommandAttrs(state2.commandBinding,focused,activeView):void 0;if(commandAttrs)activeKey.commandAttrs=commandAttrs}return activeKey},notifyPendingSequenceChange=()=>{if(!hooks.has("pendingSequence"))return;hooks.emit("pendingSequence",state.pending?collectSequencePartsFromPending(state.pending):[])};return{getFocusedTarget,getFocusedTargetIfAvailable:getFocusedTargetIfAvailable2,setPendingSequence,ensureValidPendingSequence,revalidatePendingSequenceIfNeeded,hasPendingSequenceState,getPendingSequence,popPendingSequence,getActiveKeys,getActiveKeysForCaptures,getActiveKeysForFocused,getActiveLayers,isLayerActiveForFocused:isActiveLayerForFocused,collectSequencePartsFromPending,collectMatchingBindings,collectActiveBindings}}function normalizeBindingCommand(command){if(command===void 0||typeof command==="function")return command;let trimmed=command.trim();if(!trimmed)throw Error("Invalid keymap command: command cannot be empty");return trimmed}function normalizeCommandName(name){let trimmed=name.trim();if(!trimmed)throw Error("Invalid keymap command name: name cannot be empty");if(/\s/.test(trimmed))throw Error(`Invalid keymap command name "${name}": command names cannot contain whitespace`);return trimmed}function pushCommandEntry(target,name,entry2){let existing=target.get(name);if(existing)existing.push(entry2);else target.set(name,[entry2])}function getRegisteredCommandView(state){let entries=[],chainsByName=new Map;for(let layer of state.layers)for(let commandState of layer.commands){let entry2={layer,commandState};entries.push(entry2),pushCommandEntry(chainsByName,commandState.command.name,entry2)}return{entries,chainsByName}}function collectActiveCommands(layers,conditions,checkLayerConditions){let entries=[],reachable=[],reachableByName=new Map,chainsByName=new Map;for(let layer of layers){if(layer.commands.length===0)continue;if(checkLayerConditions&&!conditions.matchesConditions(layer))continue;for(let commandState of layer.commands){if(!conditions.matchesConditions(commandState))continue;let entry2={layer,commandState};if(entries.push(entry2),pushCommandEntry(chainsByName,commandState.command.name,entry2),!reachableByName.has(commandState.command.name))reachableByName.set(commandState.command.name,entry2),reachable.push(entry2)}}return{layers,entries,reachable,reachableByName,chainsByName}}function getActiveCommandView(state,host,conditions,focused){if(state.activeLayersCacheVersion!==state.cacheVersion||state.activeLayersCacheFocused!==focused)state.activeLayersCacheVersion=state.cacheVersion,state.activeLayersCacheFocused=focused,state.activeLayersCache=getActiveLayersForFocused(state.sortedLayers,host,focused);return collectActiveCommands(state.activeLayersCache,conditions,!0)}function mergeRequirement(target,name,value,source){if(Object.prototype.hasOwnProperty.call(target,name)&&!Object.is(target[name],value))throw Error(`Conflicting keymap requirement for "${name}" from ${source}`);target[name]=value}function mergeAttribute(target,name,value,source){if(Object.prototype.hasOwnProperty.call(target,name)&&!Object.is(target[name],value))throw Error(`Conflicting keymap attribute for "${name}" from ${source}`);target[name]=value}function createFieldCompilerContext(options){let source=`field ${options.fieldName}`;return{require(name,value){mergeRequirement(options.requirements,name,value,source)},attr(name,value){if(!options.attrs)throw Error(`Keymap ${source} cannot publish attrs`);mergeAttribute(options.attrs,name,value,source)},activeWhen(matcher){options.matchers.push(options.conditions.buildRuntimeMatcher(matcher,source))}}}function isPlainObject2(value){let prototype=Object.getPrototypeOf(value);return prototype===Object.prototype||prototype===null}function getErrorMessage(error2,fallback){if(error2 instanceof Error&&error2.message)return error2.message;return fallback}function isPromiseLike(value){if(!value)return!1;if(typeof value!=="object"&&typeof value!=="function")return!1;return typeof value.then==="function"}function snapshotDataValue(value,options){let deep=options?.deep===!0,freeze=options?.freeze===!0,preserveNonPlainObjects=options?.preserveNonPlainObjects===!0;if(Array.isArray(value)){let cloned=deep?value.map((entry2)=>snapshotDataValue(entry2,options)):[...value];return freeze?Object.freeze(cloned):cloned}if(value&&typeof value==="object"){if(preserveNonPlainObjects&&!isPlainObject2(value))return value;let cloned={};for(let[key,entry2]of Object.entries(value))cloned[key]=deep?snapshotDataValue(entry2,options):entry2;return freeze?Object.freeze(cloned):cloned}return value}function createCommandCatalogService(state,host,notify,conditions,options){let registeredViewVersion=-1,registeredView,activeViewVersion=-1,activeViewFocused,activeView,registeredBindingsCacheVersion=-1,registeredBindingsCacheCommands,registeredBindingsCache,registeredBindingsByCommandVersion=-1,registeredBindingsByCommand,registeredResolvedCacheVersion=-1,registeredResolvedCache=new Map,normalizeLayerCommands=(commands)=>{return normalizeCommands({commands,commandFields:state.commandFields,conditions,onError:(code,error2,message)=>{notify.emitError(code,error2,message)}})},prependCommandResolver=(resolver)=>{return mutateCommandResolvers(()=>state.commandResolvers.prepend(resolver),resolver)},appendCommandResolver=(resolver)=>{return mutateCommandResolvers(()=>state.commandResolvers.append(resolver),resolver)},clearCommandResolvers=()=>{if(!state.commandResolvers.has())return;notify.runWithStateChangeBatch(()=>{state.commandResolvers.clear(),options.onCommandResolversChanged(),notify.queueStateChange()})},getCommands=(query2)=>{return getFilteredCommandEntries(query2).map((entry2)=>getCommand(entry2.commandState))},getCommandEntries=(query2)=>{let context=getCommandQueryContext(query2),filteredEntries=getFilteredCommandEntries(query2,context);if(filteredEntries.length===0)return[];let grouped=filteredEntries.map((entry2)=>({entry:entry2,command:getCommand(entry2.commandState),commandAttrs:entry2.commandState.attrs,bindings:[]})),indexesByName=new Map;for(let[index,item]of grouped.entries()){let existing=indexesByName.get(item.command.name);if(existing)existing.push(index);else indexesByName.set(item.command.name,[index])}if(indexesByName.size>0)collectCommandEntryBindings(grouped,indexesByName,context);return grouped.map((item)=>({command:item.command,bindings:item.bindings}))},getCommandBindings=(query2)=>{if(query2.visibility==="registered"&&registeredBindingsCacheVersion===state.derivedVersion&&registeredBindingsCacheCommands===query2.commands&&registeredBindingsCache)return registeredBindingsCache;let bindingsByCommand=new Map;for(let command of query2.commands)if(!bindingsByCommand.has(command))bindingsByCommand.set(command,[]);if(bindingsByCommand.size===0)return bindingsByCommand;if(collectCommandBindings(bindingsByCommand,getCommandQueryContext(query2)),query2.visibility==="registered")registeredBindingsCacheVersion=state.derivedVersion,registeredBindingsCacheCommands=query2.commands,registeredBindingsCache=bindingsByCommand;return bindingsByCommand},getResolvedCommandChain=(command,focused,execution)=>{let view=getActiveCommandView2(focused);if(execution){let resolved2=[],chain=view.chainsByName.get(command);if(chain)for(let entry2 of chain)resolved2.push({target:entry2.layer.target,command:entry2.commandState.command,attrs:entry2.commandState.attrs,payload:execution.payload});let fallback2=resolveCommandWithResolversForMode(command,focused,{mode:"active",execution});if(fallback2.resolved)resolved2.push(fallback2.resolved);return{entries:resolved2.length>0?resolved2:void 0,hadError:fallback2.hadError}}let resolved=[];for(let entry2 of view.chainsByName.get(command)??[])resolved.push({target:entry2.layer.target,command:entry2.commandState.command,attrs:entry2.commandState.attrs});let fallback=resolveCommandWithResolversForMode(command,focused,{mode:"active"});if(fallback.resolved)resolved.push(fallback.resolved);return{entries:resolved.length>0?resolved:void 0,hadError:fallback.hadError}},getRegisteredResolvedEntries=(command)=>{if(registeredResolvedCacheVersion!==state.derivedVersion)registeredResolvedCacheVersion=state.derivedVersion,registeredResolvedCache=new Map;if(registeredResolvedCache.has(command))return registeredResolvedCache.get(command)??void 0;let resolved=resolveRegisteredEntries(getRegisteredCommandChain(command));return registeredResolvedCache.set(command,resolved??null),resolved},getActiveRegisteredResolvedEntries=(command,focused)=>{return resolveRegisteredEntries(getActiveCommandView2(focused).chainsByName.get(command))},resolveRegisteredResolverFallback=(command,execution)=>{return resolveCommandWithResolversForMode(command,null,{mode:"registered",execution})},resolveActiveResolverFallback=(command,focused,execution)=>{return resolveCommandWithResolversForMode(command,focused,{mode:"active",execution})},getTopCommand=(command,focused)=>{return getTopResolvedCommand(command,focused)?.command},getCommandByName=(command)=>{return getCommandEntry(command)?.commandState.command},getDispatchUnavailableCommandState=(command,focused,includeCommand)=>{let chain=getCommandView().chainsByName.get(command);if(!chain||chain.length===0)return;let inactiveEntry,disabledEntry;for(let entry2 of chain){if(!isLayerActiveForFocused(host,entry2.layer,focused)){inactiveEntry??=entry2;continue}if(!conditions.matchesConditions(entry2.layer)||!conditions.matchesConditions(entry2.commandState))disabledEntry??=entry2}let unavailableEntry=disabledEntry??inactiveEntry;if(!unavailableEntry)return;return{reason:disabledEntry?"disabled":"inactive",command:includeCommand?unavailableEntry.commandState.command:void 0}},getActiveCommandView2=(focused)=>{if(activeViewVersion===state.derivedVersion&&activeViewFocused===focused&&activeView)return activeView;let view=getActiveCommandView(state,host,conditions,focused);if(activeCommandViewCanCache())activeViewVersion=state.derivedVersion,activeViewFocused=focused,activeView=view;return view},getCommandView=()=>{if(registeredViewVersion===state.derivedVersion&&registeredView)return registeredView;return registeredViewVersion=state.derivedVersion,registeredView=getRegisteredCommandView(state),registeredView},activeCommandViewCanCache=()=>{return state.activeCommandViewCacheBlockers===0},isBindingVisible=(binding,focused,activeView2)=>{if(binding.command===void 0||binding.run)return!0;if(typeof binding.command!=="string")return!1;if(activeView2.reachableByName.has(binding.command))return!0;return getFallbackResolvedCommand(binding.command,focused,"active")!==void 0},getBindingCommandAttrs=(binding,focused,activeView2)=>{if(typeof binding.command!=="string")return;let active=activeView2.reachableByName.get(binding.command);if(active)return active.commandState.attrs;return getFallbackResolvedCommand(binding.command,focused,"active")?.attrs},getCommandResolutionStatus=(command,layerCommands)=>{if(layerCommands?.some((state2)=>state2.command.name===command)||getCommandView().chainsByName.has(command))return"resolved";let lookup=resolveCommandWithResolversForMode(command,getFocusedTargetIfAvailable(host));if(lookup.resolved||lookup.hadError)return lookup.resolved?"resolved":"error";return"unresolved"},mutateCommandResolvers=(register2,resolver)=>{return notify.runWithStateChangeBatch(()=>{let off=register2();return options.onCommandResolversChanged(),notify.queueStateChange(),()=>{notify.runWithStateChangeBatch(()=>{if(off(),state.commandResolvers.values().includes(resolver))return;options.onCommandResolversChanged(),notify.queueStateChange()})}})},getTopResolvedCommand=(command,focused)=>{let active=getActiveCommandView2(focused).reachableByName.get(command);if(active)return{target:active.layer.target,command:active.commandState.command,attrs:active.commandState.attrs};return getFallbackResolvedCommand(command,focused,"active")},getCommandEntry=(command)=>{return getRegisteredCommandChain(command)?.[0]},getRegisteredCommandChain=(command)=>{let entries=[];for(let layer of state.sortedLayers)for(let commandState of layer.commands)if(commandState.command.name===command)entries.push({layer,commandState});return entries.length>0?entries:void 0},resolveRegisteredEntries=(chain)=>{if(!chain?.length)return;return chain.map((entry2)=>({target:entry2.layer.target,command:entry2.commandState.command,attrs:entry2.commandState.attrs}))},getFallbackResolvedCommand=(command,focused,mode)=>{return resolveCommandWithResolversForMode(command,focused,{mode}).resolved},getRegisteredLayerCommandEntries=()=>{return getCommandView().entries},getRegisteredBindingsByCommand=()=>{if(registeredBindingsByCommandVersion===state.derivedVersion&&registeredBindingsByCommand)return registeredBindingsByCommand;let bindingsByCommand=new Map;for(let layer of state.layers)for(let binding of layer.bindings){if(typeof binding.command!=="string")continue;let bindings=bindingsByCommand.get(binding.command);if(bindings)bindings.push(binding);else bindingsByCommand.set(binding.command,[binding])}return registeredBindingsByCommandVersion=state.derivedVersion,registeredBindingsByCommand=bindingsByCommand,bindingsByCommand},getCommandQueryContext=(query2)=>{let visibility=query2?.visibility??"reachable",focused=query2&&Object.prototype.hasOwnProperty.call(query2,"focused")?query2.focused??null:getFocusedTargetIfAvailable(host);if(visibility==="registered")return{visibility,focused};return{visibility,focused,activeView:getActiveCommandView2(focused)}},getFilteredCommandEntries=(query2,context=getCommandQueryContext(query2))=>{let entries;if(context.visibility==="registered")entries=getRegisteredLayerCommandEntries();else if(context.visibility==="active")entries=context.activeView?.entries??[];else entries=context.activeView?.reachable??[];return queryLayerCommandEntries({entries,query:query2,getCommand:(command)=>getCommand(command),onFilterError:(error2)=>{notify.emitError("command-query-filter-error",error2,"[Keymap] Error in command query filter:")}})},collectCommandEntryBindings=(grouped,indexesByName,context)=>{visitCommandQueryBindings(context,(binding)=>{collectBindingForCommandEntries(grouped,indexesByName,binding)})},collectCommandBindings=(bindingsByCommand,context)=>{if(context.visibility==="registered"){let registeredBindings=getRegisteredBindingsByCommand();for(let[command,bindings]of bindingsByCommand){let commandAttrs=getCommandView().chainsByName.get(command)?.[0]?.commandState.attrs;for(let binding of registeredBindings.get(command)??[])bindings.push(createActiveBinding(binding,commandAttrs))}return}visitCommandQueryBindings(context,(binding)=>{collectBindingForCommandBindings(bindingsByCommand,binding,context)})},visitCommandQueryBindings=(context,visit)=>{if(context.visibility==="registered"){for(let layer of state.layers)for(let binding of layer.bindings)visit(binding);return}let activeView2=context.activeView;if(!activeView2)return;for(let layer of activeView2.layers){if(layer.bindings.length===0||!conditions.matchesConditions(layer))continue;for(let binding of layer.bindings)if(conditions.matchesConditions(binding)&&isBindingVisible(binding,context.focused,activeView2))visit(binding)}},collectBindingForCommandEntries=(grouped,indexesByName,binding)=>{if(typeof binding.command!=="string")return;let indexes=indexesByName.get(binding.command);if(!indexes||indexes.length===0)return;for(let index of indexes){let item=grouped[index];if(!item)continue;item.bindings.push(createActiveBinding(binding,item.commandAttrs))}},collectBindingForCommandBindings=(bindingsByCommand,binding,context)=>{if(typeof binding.command!=="string")return;let bindings=bindingsByCommand.get(binding.command);if(!bindings)return;bindings.push(createActiveBinding(binding,getCommandBindingAttrsForQuery(binding,context)))},createActiveBinding=(binding,commandAttrs)=>{return{sequence:binding.sequence,command:binding.command,commandAttrs,attrs:binding.attrs,event:binding.event,preventDefault:binding.preventDefault,fallthrough:binding.fallthrough}},getCommandBindingAttrsForQuery=(binding,context)=>{if(typeof binding.command!=="string")return;if(context.visibility==="registered")return getCommandView().chainsByName.get(binding.command)?.[0]?.commandState.attrs;let activeView2=context.activeView;if(!activeView2)return;return getBindingCommandAttrs(binding,context.focused,activeView2)},resolveCommandWithResolversForMode=(command,focused,options2)=>{let mode=options2?.mode??"active",execution=options2?.execution??{input:command},lookup=resolveCommandWithResolvers(command,state.commandResolvers.values(),()=>createCommandResolverContext(focused,mode,execution),(error2)=>{notify.emitError("command-resolver-error",error2,`[Keymap] Error in command resolver for "${command}":`)}),resolved=lookup.resolved;if(resolved){let entry2=getCommandEntryForMode(resolved.command.name,focused,mode);if(entry2?.commandState.command===resolved.command&&resolved.target===void 0)resolved={...resolved,target:entry2.layer.target},lookup.resolved=resolved}if(resolved&&!resolved.attrs){let attrs=getCommandStateAttrs(resolved.command.name,focused,mode)??getResolverCommandAttrs(resolved.command);if(attrs)lookup.resolved={...resolved,attrs}}return lookup},getCommandStateAttrs=(command,focused,mode)=>{if(mode==="registered")return getCommandEntry(command)?.commandState.attrs;return getActiveCommandView2(focused).reachableByName.get(command)?.commandState.attrs},getCommandEntryForMode=(command,focused,mode)=>{if(mode==="registered")return getCommandEntry(command);return getActiveCommandView2(focused).reachableByName.get(command)},createCommandResolverContext=(focused,mode,execution)=>{let{input,payload}=execution;return{context:{get input(){return input},get payload(){return payload},setInput(nextInput){input=nextInput},setPayload(nextPayload){payload=nextPayload},getCommand:(name)=>{if(mode==="registered")return getCommandByName(name);return getTopCommand(name,focused)}},getExecutionFields(){return{input,payload}}}};return{normalizeCommands:normalizeLayerCommands,prependCommandResolver,appendCommandResolver,clearCommandResolvers,getCommands,getCommandEntries,getCommandBindings,getResolvedCommandChain,getRegisteredResolvedEntries,getActiveRegisteredResolvedEntries,resolveRegisteredResolverFallback,resolveActiveResolverFallback,getTopCommand,getDispatchUnavailableCommandState,getActiveCommandView:getActiveCommandView2,isBindingVisible,getBindingCommandAttrs,getCommandResolutionStatus}}function getCommand(state){return state.command}function normalizeCommands(options){let normalizedCommands=[],seen=new Set;for(let command of options.commands)try{let mergedRequires={},matchers=[],normalizedName=normalizeCommandName(command.name),fields=getCommandFields(command),attrs={};if(seen.has(normalizedName)){options.onError("duplicate-command",{command:normalizedName},`Duplicate keymap command "${normalizedName}" in the same layer`);continue}command.name=normalizedName;for(let[fieldName,value]of Object.entries(fields)){if(value===void 0)continue;let compiler=options.commandFields.get(fieldName);if(!compiler)continue;compiler(value,createFieldCompilerContext({fieldName,conditions:options.conditions,requirements:mergedRequires,matchers,attrs}))}let commandState={command,fields,attrs:Object.keys(attrs).length===0?void 0:attrs,requires:Object.entries(mergedRequires),matchers};seen.add(commandState.command.name),normalizedCommands.push(commandState)}catch(error2){options.onError("register-command-failed",error2,getErrorMessage(error2,`Failed to register keymap command "${String(command.name)}"`));continue}return normalizedCommands}function resolveCommandWithResolvers(command,resolvers,createContext3,onResolverError){if(resolvers.length===0)return{hadError:!1};let hadError=!1;for(let resolver of resolvers){let resolvedCommand,attempt=createContext3();try{resolvedCommand=resolver(command,attempt.context)}catch(error2){hadError=!0,onResolverError(error2);continue}if(resolvedCommand)return{hadError,resolved:getResolverCommandEntry(resolvedCommand,attempt.getExecutionFields())}}return{hadError}}function getCommandFields(command){let fields={};for(let[name,value]of Object.entries(command))if(!RESERVED_COMMAND_FIELDS.has(name)&&value!==void 0)fields[name]=value;return Object.keys(fields).length===0?EMPTY_COMMAND_FIELDS:fields}function getResolverCommandEntry(command,execution){return{command,input:execution.input,payload:execution.payload}}function getResolverCommandAttrs(command){let fields=getCommandFields(command);return fields===EMPTY_COMMAND_FIELDS?void 0:fields}function queryLayerCommandEntries(options){let namespace=options.query?.namespace,limit=normalizeQueryLimit(options.query?.limit);if(limit===0)return[];let normalizedSearch=options.query?.search?.trim().toLowerCase()??"",searchKeys=DEFAULT_COMMAND_SEARCH_FIELDS;if(options.query?.searchIn&&options.query.searchIn.length>0)searchKeys=options.query.searchIn;let filter=options.query?.filter,filterEntries2,filterPredicate,exactNameFilter;if(typeof filter==="function")filterPredicate=filter;else if(filter){let entries=Object.entries(filter),remainingEntries=[];for(let[key,matcher]of entries){if(key==="name"){if(typeof matcher==="string"){exactNameFilter=new Set([matcher]);continue}if(Array.isArray(matcher)){let names=new Set;for(let value of matcher)if(typeof value==="string")names.add(value);exactNameFilter=names;continue}}remainingEntries.push([key,matcher])}filterEntries2=remainingEntries.length>0?remainingEntries:void 0}let results=[];for(let entry2 of options.entries){let commandState=entry2.commandState;if(!commandMatchesNamespace(commandState,namespace))continue;if(!commandMatchesSearch(commandState,normalizedSearch,searchKeys))continue;if(exactNameFilter&&!exactNameFilter.has(commandState.command.name))continue;if(!commandMatchesFilters(commandState,filterEntries2,options))continue;if(filterPredicate){let matches=!1;try{matches=filterPredicate(options.getCommand(commandState))}catch(error2){options.onFilterError(error2);continue}if(!matches)continue}if(results.push(entry2),limit!==void 0&&results.length>=limit)break}return results}function normalizeQueryLimit(value){if(value===void 0)return;let limit=Math.floor(Number(value));if(!Number.isFinite(limit)||limit<=0)return 0;return limit}function commandMatchesSearch(commandState,search,searchKeys){if(!search)return!0;for(let key of searchKeys)if(commandKeyMatchesSearch(commandState,key,search))return!0;return!1}function commandMatchesNamespace(commandState,namespace){if(namespace===void 0)return!0;let fields=commandState.fields;if(!Object.prototype.hasOwnProperty.call(fields,"namespace"))return!1;return valueMatchesFilter(fields.namespace,namespace)}function commandMatchesFilters(commandState,filters,options){if(!filters)return!0;for(let[key,matcher]of filters)if(!commandKeyMatchesQuery(commandState,key,matcher,options))return!1;return!0}function commandKeyMatchesSearch(commandState,key,search){return getCommandSearchText(commandState,key)?.includes(search)===!0}function getCommandSearchText(commandState,key){let cache=commandSearchCache.get(commandState);if(!cache)cache=new Map,commandSearchCache.set(commandState,cache);if(cache.has(key))return cache.get(key);let{fields,attrs}=commandState,value;if(key==="name")value=commandState.command.name;else if(Object.prototype.hasOwnProperty.call(fields,key))value=fields[key];else if(attrs&&Object.prototype.hasOwnProperty.call(attrs,key))value=attrs[key];let text=toSearchText(value);return cache.set(key,text),text}function toSearchText(value){if(Array.isArray(value)){let parts=[];for(let entry2 of value){let text=toSearchText(entry2);if(text!==void 0)parts.push(text)}return parts.length>0?parts.join("\x00"):void 0}if(typeof value==="string")return value.toLowerCase();if(typeof value==="number"||typeof value==="boolean"||typeof value==="bigint")return String(value).toLowerCase();return}function runCommandQueryPredicate(matcher,value,command,onFilterError){try{return matcher(value,command)}catch(error2){return onFilterError(error2),!1}}function commandKeyMatchesQuery(commandState,key,matcher,options){if(typeof matcher==="function")return commandKeyMatchesPredicate(commandState,key,matcher,options);return commandKeyMatchesExact(commandState,key,matcher)}function commandKeyMatchesPredicate(commandState,key,matcher,options){let{command,fields,attrs}=commandState,commandView,foundValue=!1,getCommandView=()=>commandView??=options.getCommand(commandState);if(key==="name"){if(foundValue=!0,runCommandQueryPredicate(matcher,command.name,getCommandView(),options.onFilterError))return!0}if(Object.prototype.hasOwnProperty.call(fields,key)){if(foundValue=!0,runCommandQueryPredicate(matcher,fields[key],getCommandView(),options.onFilterError))return!0}if(attrs&&Object.prototype.hasOwnProperty.call(attrs,key)){if(foundValue=!0,runCommandQueryPredicate(matcher,attrs[key],getCommandView(),options.onFilterError))return!0}return!foundValue&&runCommandQueryPredicate(matcher,void 0,getCommandView(),options.onFilterError)}function commandKeyMatchesExact(commandState,key,matcher){let{command,fields,attrs}=commandState;if(key==="name"&&valueMatchesFilter(command.name,matcher))return!0;if(Object.prototype.hasOwnProperty.call(fields,key)&&valueMatchesFilter(fields[key],matcher))return!0;return!!attrs&&Object.prototype.hasOwnProperty.call(attrs,key)&&valueMatchesFilter(attrs[key],matcher)}function valueMatchesFilter(value,matcher){if(Array.isArray(matcher))return matcher.some((expected)=>valueMatchesExact(value,expected));return valueMatchesExact(value,matcher)}function valueMatchesExact(value,expected){if(Array.isArray(value))return value.some((entry2)=>valueMatchesExact(entry2,expected));return Object.is(value,expected)}function createCommandExecutorService(notify,runtime,activation,catalog,options){let createCommandContext=(event,focused,target,data,input,payload)=>{return{keymap:options.keymap,event,focused,target,data,input,payload}},executeResolvedCommand=(commandName,command,context,includeCommand)=>{let commandView=typeof command==="function"?void 0:command,run=typeof command==="function"?command:command.run,resultCommand=includeCommand?commandView:void 0,result2;try{result2=run(commandView?{...context,command:commandView}:context)}catch(error2){return notify.emitError("command-execution-error",error2,`[Keymap] Error running command "${commandName}":`),{status:"error",result:resultCommand?{ok:!1,reason:"error",command:resultCommand}:{ok:!1,reason:"error"}}}if(isPromiseLike(result2))return result2.catch((error2)=>{notify.emitError("async-command-error",error2,`[Keymap] Async error in command "${commandName}":`)}),{status:"handled",result:resultCommand?{ok:!0,command:resultCommand}:{ok:!0}};if(isRunCommandResult(result2)){let commandResult=result2;if(!result2.ok&&result2.reason!=="not-found"&&includeCommand&&commandView&&!result2.command)commandResult={...result2,command:commandView};else if(result2.ok&&includeCommand&&commandView&&!result2.command)commandResult={...result2,command:commandView};return{status:result2.ok?"handled":"rejected",result:commandResult}}if(result2===!1)return{status:"rejected",result:resultCommand?{ok:!1,reason:"rejected",command:resultCommand}:{ok:!1,reason:"rejected"}};return{status:"handled",result:resultCommand?{ok:!0,command:resultCommand}:{ok:!0}}},executeCommandChain=(commandName,chain,event,focused,target,data,payload,includeCommand)=>{let rejected;for(let entry2 of chain??[]){let executed=executeResolvedCommand(commandName,entry2.command,createCommandContext(event,focused,target??entry2.target??null,data,commandName,payload),includeCommand);if(executed.status==="handled"||executed.status==="error")return[executed.result,rejected];rejected=executed.result}return[void 0,rejected]},executeProgrammaticCommand=(cmd,commandOptions,mode)=>{let normalized;try{normalized=normalizeBindingCommand(cmd)}catch{return{ok:!1,reason:"invalid-args"}}if(typeof normalized!=="string")return{ok:!1,reason:"not-found"};let includeCommand=commandOptions?.includeCommand===!0,focused=commandOptions?.focused??activation.getFocusedTargetIfAvailable(),event=commandOptions?.event??options.createCommandEvent(),data=runtime.getReadonlyData(),payload=commandOptions?.payload,chain=mode==="registered"?catalog.getRegisteredResolvedEntries(normalized):catalog.getActiveRegisteredResolvedEntries(normalized,focused),[done,rejected]=executeCommandChain(normalized,chain,event,focused,commandOptions?.target,data,payload,includeCommand);if(done)return done;let rejectedResult=rejected,fallback=mode==="registered"?catalog.resolveRegisteredResolverFallback(normalized,{input:normalized,payload}):catalog.resolveActiveResolverFallback(normalized,focused,{input:normalized,payload});if(fallback.resolved){let result2=executeResolvedCommand(normalized,fallback.resolved.command,createCommandContext(event,focused,commandOptions?.target??fallback.resolved.target??null,data,fallback.resolved.input??normalized,fallback.resolved.payload),includeCommand);if(result2.status==="handled"||result2.status==="error")return result2.result;rejectedResult=result2.result}if(fallback.hadError)return{ok:!1,reason:"error"};if(mode==="active"){let unavailable2=catalog.getDispatchUnavailableCommandState(normalized,focused,includeCommand);if(unavailable2)return unavailable2.command?{ok:!1,reason:unavailable2.reason,command:unavailable2.command}:{ok:!1,reason:unavailable2.reason}}return rejectedResult??{ok:!1,reason:"not-found"}};return{runCommand(cmd,commandOptions){return executeProgrammaticCommand(cmd,commandOptions,"registered")},dispatchCommand(cmd,commandOptions){return executeProgrammaticCommand(cmd,commandOptions,"active")},runBinding(bindingLayer,binding,event,focused,payload){let data=runtime.getReadonlyData();if(binding.run){if(executeResolvedCommand(typeof binding.command==="string"?binding.command:"<function>",binding.run,createCommandContext(event,focused,bindingLayer.target??null,data,typeof binding.command==="string"?binding.command:"<function>",payload),!1).status==="rejected")return!1;return applyBindingEventEffects(binding,event),!0}if(typeof binding.command!=="string")return!1;let chain=catalog.getResolvedCommandChain(binding.command,focused,payload===void 0?void 0:{input:binding.command,payload}).entries;for(let entry2 of chain??[]){if(executeResolvedCommand(binding.command,entry2.command,createCommandContext(event,focused,entry2.target??bindingLayer.target??null,data,entry2.input??binding.command,entry2.payload),!1).status==="rejected")continue;return applyBindingEventEffects(binding,event),!0}return!1}}}function isRunCommandResult(value){return typeof value==="object"&&value!==null&&"ok"in value}function applyBindingEventEffects(binding,event){if(!binding.preventDefault)return;event.preventDefault(),event.stopPropagation()}function snapshotAttributes(attrs){if(Object.keys(attrs).length===0)return;return snapshotDataValue(attrs,{freeze:!0})}function createCompilerService(state,notify,conditions,options){let parseTokenKey=(key)=>{return parseSingleKeyPartWithParsers(key,state.bindingParsers.values(),{tokens:state.tokens,patterns:state.patterns,layer:EMPTY_COMPILE_FIELDS,parseObjectKey:(value,options2)=>parseObjectKeyPart(value,options2)})},parseKeySequence=(key)=>{if(typeof key!=="string")return[parseObjectKeyPart(key)];let parsed=parseBindingSequenceWithParsers(key,state.bindingParsers.values(),{tokens:state.tokens,patterns:state.patterns,layer:EMPTY_COMPILE_FIELDS,parseObjectKey:(value,options2)=>parseObjectKeyPart(value,options2)});for(let tokenName of parsed.unknownTokens)options.warnUnknownToken(tokenName,key);return parsed.parts},formatKey=(key,options2)=>{return stringifyKeySequence(parseKeySequence(key),options2)},compileBindings=(bindings,tokens2,sourceTarget,sourceLayerOrder,compileFields)=>{let bindingStates=[],hasTokenBindings=!1,bindingExpanders=state.bindingExpanders.values(),bindingParsers=state.bindingParsers.values(),bindingFieldCompilers=state.bindingFields,allowExactPrefixAmbiguity=state.disambiguationResolvers.has(),warnUnknownField=options.warnUnknownField,warnUnknownToken=options.warnUnknownToken;for(let[bindingIndex,binding]of bindings.entries()){let expandedBindingKeys;try{expandedBindingKeys=expandBindingKeyWithExpanders(binding.key,bindingExpanders,{layer:compileFields})}catch(error2){notify.emitError("binding-expand-error",error2,getErrorMessage(error2,"Failed to expand keymap binding"));continue}for(let expandedBindingKey of expandedBindingKeys){let expandedKey=expandedBindingKey.key,parsed;try{parsed=typeof expandedKey==="string"?parseBindingSequenceWithParsers(expandedKey,bindingParsers,{tokens:tokens2,patterns:state.patterns,layer:compileFields,parseObjectKey:(value,options2)=>parseObjectKeyPart(value,options2)}):{parts:[parseObjectKeyPart(expandedKey)],usedTokens:[],unknownTokens:[],hasTokenBindings:!1},parsed=applyExpansionDisplays(parsed,expandedBindingKey)}catch(error2){notify.emitError("binding-parse-error",error2,getErrorMessage(error2,"Failed to parse keymap binding"));continue}let sequence=parsed.parts;hasTokenBindings||=parsed.hasTokenBindings;for(let tokenName of parsed.unknownTokens)warnUnknownToken(tokenName,typeof expandedKey==="string"?expandedKey:String(expandedKey.name));for(let compiledInput of applyBindingTransformers(binding,sequence,tokens2,bindingParsers,compileFields))try{let event=normalizeBindingEvent(compiledInput.event),compiledSequence=compiledInput.sequence,mergedRequires={},mergedAttrs={},matchers=[];for(let fieldName in compiledInput){if(fieldName==="sequence")continue;if(RESERVED_BINDING_FIELDS.has(fieldName))continue;let value=compiledInput[fieldName];if(value===void 0)continue;let compiler=bindingFieldCompilers.get(fieldName);if(!compiler){warnUnknownField("binding",fieldName);continue}compiler(value,createFieldCompilerContext({fieldName,conditions,requirements:mergedRequires,matchers,attrs:mergedAttrs}))}let attrs=Object.keys(mergedAttrs).length>0?snapshotAttributes(mergedAttrs):void 0,command=normalizeBindingCommand(compiledInput.cmd),compiledBinding={binding,sequence:compiledSequence,command,event,parsedBinding:snapshotParsedBinding(compiledInput),sourceTarget,sourceLayerOrder,bindingIndex,requires:Object.keys(mergedRequires).length>0?Object.entries(mergedRequires):EMPTY_REQUIRES,matchers:matchers.length>0?matchers:EMPTY_MATCHERS,preventDefault:compiledInput.preventDefault!==!1,fallthrough:compiledInput.fallthrough??!1};if(attrs)compiledBinding.attrs=attrs;if(typeof command==="function")compiledBinding.run=command;if(compiledSequence.length===0)continue;if(event==="release"&&compiledSequence.length>1)throw Error("Keymap release bindings only support a single key stroke");let terminalPattern=compiledSequence.at(-1);if(terminalPattern?.patternName){let pattern=state.patterns.get(terminalPattern.patternName);if(pattern&&pattern.max!==pattern.min)throw Error("Keymap unbounded sequence patterns must be followed by a concrete continuation")}if(event==="press"&&!allowExactPrefixAmbiguity)validateExactPrefixAmbiguity(bindingStates,compiledBinding);bindingStates.push(compiledBinding)}catch(error2){notify.emitError("binding-compile-error",error2,getErrorMessage(error2,"Failed to compile keymap binding"))}}}return{bindings:bindingStates,hasTokenBindings}},parseObjectKeyPart=(key,options2)=>{return createKeySequencePart(key,options2)},normalizeBindingEvent=(event)=>{if(event===void 0||event==="press")return"press";if(event==="release")return"release";throw Error(`Invalid keymap binding event "${String(event)}": expected "press" or "release"`)},applyBindingTransformers=(binding,sequence,tokens2,bindingParsers,compileFields)=>{let bindingTransformers=state.bindingTransformers.values();if(bindingTransformers.length===0)return[{...binding,sequence:cloneKeySequence(sequence)}];let parsedBinding={...binding,sequence:cloneKeySequence(sequence)},extraBindings=[],keepOriginal=!0,layer=compileFields??EMPTY_COMPILE_FIELDS;for(let transformer of bindingTransformers)try{transformer(parsedBinding,{layer,parseKey:(key)=>{return parseSingleKeyPartWithParsers(key,bindingParsers,{tokens:tokens2,patterns:state.patterns,layer,parseObjectKey:(value,options2)=>parseObjectKeyPart(value,options2)})},add:(nextBinding)=>{extraBindings.push(snapshotParsedBinding(nextBinding))},skipOriginal:()=>{keepOriginal=!1}})}catch(error2){notify.emitError("binding-transformer-error",error2,"[Keymap] Error in binding transformer:")}if(!keepOriginal)return extraBindings;if(extraBindings.length===0)return[parsedBinding];return[parsedBinding,...extraBindings]};return{parseTokenKey,parseKeySequence,formatKey,compileBindings}}function sequenceMatchesPrefix(left,right){if(left.length>=right.length)return!1;for(let index=0;index<left.length;index+=1)if(left[index]?.match!==right[index]?.match)return!1;return!0}function validateExactPrefixAmbiguity(bindings,next){for(let existing of bindings){if(existing.event!=="press")continue;if(existing.command!==void 0&&sequenceMatchesPrefix(existing.sequence,next.sequence)||next.command!==void 0&&sequenceMatchesPrefix(next.sequence,existing.sequence))throw Error("Keymap bindings cannot use the same sequence as both an exact match and a prefix in the same layer")}}function expandBindingKeyWithExpanders(key,expanders,options){if(typeof key!=="string"||expanders.length===0)return[{key}];let layer=options?.layer??EMPTY_COMPILE_FIELDS,candidates=[{key}];for(let expander of expanders){let nextCandidates=[];for(let candidate of candidates){let result2=expander({input:candidate.key,displays:candidate.displays,layer});if(!result2){nextCandidates.push(candidate);continue}if(result2.length===0)throw Error(`Keymap binding expander must return at least one key sequence for "${candidate.key}"`);for(let expanded of result2){if(!expanded||typeof expanded!=="object"||Array.isArray(expanded)||typeof expanded.key!=="string")throw Error(`Keymap binding expander must return expansion objects with string keys for "${candidate.key}"`);if(expanded.displays!==void 0){if(!Array.isArray(expanded.displays))throw Error(`Keymap binding expander displays must be an array of strings for "${candidate.key}"`);for(let display of expanded.displays)if(typeof display!=="string")throw Error(`Keymap binding expander displays must be an array of strings for "${candidate.key}"`)}nextCandidates.push(expanded)}}candidates=nextCandidates}return candidates}function applyExpansionDisplays(parsed,expansion){if(!expansion.displays)return parsed;if(expansion.displays.length!==parsed.parts.length)throw Error(`Keymap binding expansion displays length must match parsed sequence length for "${String(expansion.key)}"`);return{...parsed,parts:parsed.parts.map((part,index)=>({...part,display:expansion.displays[index]}))}}function parseBindingSequenceWithParsers(key,parsers2,options){if(key.length===0)throw Error("Invalid key sequence: sequence cannot be empty");if(parsers2.length===0)throw Error("No keymap binding parsers are registered");let tokens2=options.tokens??new Map,patterns2=options.patterns??new Map,layer=options.layer??EMPTY_COMPILE_FIELDS,parseObjectKey=options.parseObjectKey,parts=[],usedTokens=new Set,unknownTokens=new Set,index=0;while(index<key.length){let matched=!1;for(let parser of parsers2){let result2=parser({input:key,index,layer,tokens:tokens2,patterns:patterns2,normalizeTokenName:normalizeBindingTokenName,createMatch:createTextKeyMatch,parseObjectKey});if(!result2)continue;if(result2.nextIndex<=index||result2.nextIndex>key.length)throw Error(`Keymap binding parser must advance the input for "${key}" at index ${index}`);parts.push(...result2.parts);for(let tokenName of result2.usedTokens??[])usedTokens.add(tokenName);for(let tokenName of result2.unknownTokens??[])unknownTokens.add(tokenName);index=result2.nextIndex,matched=!0;break}if(!matched)throw Error(`No keymap binding parser handled input at index ${index} in "${key}"`)}return{parts,usedTokens:[...usedTokens],unknownTokens:[...unknownTokens],hasTokenBindings:usedTokens.size>0||unknownTokens.size>0}}function parseSingleKeyPartWithParsers(key,parsers2,options){if(typeof key!=="string")return options.parseObjectKey(key);let{parts}=parseBindingSequenceWithParsers(key,parsers2,options),[part]=parts;if(!part||parts.length!==1)throw Error(`Invalid key "${String(key)}": expected a single key stroke`);return part}function isReactiveMatcher(value){if(!value||typeof value!=="object")return!1;let candidate=value;return typeof candidate.get==="function"&&typeof candidate.subscribe==="function"}function createConditionService(state,notify){let hasNoConditions=(target)=>{return target.requires.length===0&&target.matchers.length===0},matchesRuntimeMatcher=(matcher)=>{try{return matcher.match()}catch(error2){return notify.emitError("runtime-matcher-error",error2,`[Keymap] Error evaluating runtime matcher from ${matcher.source}:`),!1}},matchesRuntimeMatchers=(target)=>{if(target.matchers.length===0)return!0;if(target.matchers.length===1){let[matcher]=target.matchers;return matcher?matchesRuntimeMatcher(matcher):!0}for(let matcher of target.matchers)if(!matchesRuntimeMatcher(matcher))return!1;return!0},matchRequirements=(requires)=>{if(requires.length===0)return!0;for(let[name,value]of requires)if(!Object.is(state.data[name],value))return!1;return!0};return{buildRuntimeMatcher(matcher,source){if(typeof matcher==="function")return{source,match:matcher};if(isReactiveMatcher(matcher))return{source,match:()=>matcher.get(),subscribe:(onChange)=>matcher.subscribe(onChange)};throw Error(`Keymap ${source} expected a function or a reactive matcher`)},matchesConditions:(target)=>{return hasNoConditions(target)||matchRequirements(target.requires)&&matchesRuntimeMatchers(target)}}}function createSyncDecision(action,handler){return{[KEY_DISAMBIGUATION_DECISION]:!0,action,handler}}function createDeferredDecision(action){return{[KEY_DEFERRED_DISAMBIGUATION_DECISION]:!0,action}}function isSyncDecision(value){return!!value&&typeof value==="object"&&value[KEY_DISAMBIGUATION_DECISION]===!0}function isDeferredDecision(value){return!!value&&typeof value==="object"&&value[KEY_DEFERRED_DISAMBIGUATION_DECISION]===!0}function sleepWithSignal(ms,signal){if(signal.aborted)return Promise.resolve(!1);return new Promise((resolve23)=>{let timeout=setTimeout(()=>{signal.removeEventListener("abort",onAbort),resolve23(!0)},Math.max(0,ms)),onAbort=()=>{clearTimeout(timeout),signal.removeEventListener("abort",onAbort),resolve23(!1)};signal.addEventListener("abort",onAbort,{once:!0})})}function matchSequencePattern(patterns2,notify,patternName,event){let pattern=patterns2.get(patternName);if(!pattern)return;try{return pattern.matcher(event)}catch(error2){notify.emitError("sequence-pattern-match-error",error2,`[Keymap] Error matching sequence pattern "${pattern.name}":`);return}}function createPatternEventPart(patterns2,event,patternName,match){let payloadKey=patterns2.get(patternName)?.payloadKey??patternName;return{...createKeySequencePart({name:event.name,ctrl:event.ctrl,shift:event.shift,meta:event.meta,super:event.super??!1,hyper:event.hyper||void 0},{display:match.display??String(match.value??event.name)}),patternName,payloadKey}}function createSequencePayload(patterns2,notify,capture2){if(!capture2?.patterns||capture2.patterns.length===0)return;let payload={},hasPayload=!1;for(let captured of capture2.patterns){let pattern=patterns2.get(captured.name),value;try{value=pattern?.finalize?pattern.finalize(captured.values):captured.values.length===1?captured.values[0]:[...captured.values]}catch(error2){notify.emitError("sequence-pattern-finalize-error",error2,`[Keymap] Error finalizing sequence pattern "${captured.name}":`);continue}let existing=payload[captured.payloadKey];if(existing===void 0)payload[captured.payloadKey]=value,hasPayload=!0;else if(Array.isArray(existing))existing.push(value);else payload[captured.payloadKey]=[existing,value]}return hasPayload?payload:void 0}function createDispatchService(state,notify,runtime,activation,conditions,executor,compiler,catalog,layers,hooks){let eventMatchResolverContext={resolveKey:(key)=>compiler.parseTokenKey(key).match},pendingDisambiguation=null,nextPendingDisambiguationId=0;function intercept(name,fn,options){if(name==="key"){let keyOptions=options;return state.keyHooks.register(fn,{priority:keyOptions?.priority??0,release:keyOptions?.release??!1})}if(name==="key:after"){let keyOptions=options;return state.keyAfterHooks.register(fn,{priority:keyOptions?.priority??0,release:keyOptions?.release??!1})}let rawOptions=options;return state.rawHooks.register(fn,{priority:rawOptions?.priority??0})}function prependEventMatchResolver(resolver){return state.eventMatchResolvers.prepend(resolver)}function appendEventMatchResolver(resolver){return state.eventMatchResolvers.append(resolver)}function clearEventMatchResolvers(){state.eventMatchResolvers.clear()}function prependDisambiguationResolver(resolver){return mutateDisambiguationResolvers(()=>state.disambiguationResolvers.prepend(resolver),resolver)}function appendDisambiguationResolver(resolver){return mutateDisambiguationResolvers(()=>state.disambiguationResolvers.append(resolver),resolver)}function clearDisambiguationResolvers(){if(!state.disambiguationResolvers.has())return;notify.runWithStateChangeBatch(()=>{state.disambiguationResolvers.clear(),layers.recompileBindings()})}function handlePendingSequenceChange(_previous,_next){if(!pendingDisambiguation)return;cancelPendingDisambiguation()}function handleRawSequence(sequence){let hooks2=state.rawHooks.entries();if(hooks2.length===0)return!1;let stopped=!1,context={sequence,stop(){stopped=!0}};for(let hook of hooks2){try{hook.listener(context)}catch(error2){notify.emitError("raw-intercept-error",error2,"[Keymap] Error in raw intercept listener:")}if(stopped)return!0}return!1}function createDispatchBinding(binding,focused){return{sequence:cloneKeySequence(binding.sequence),command:binding.command,commandAttrs:catalog.getBindingCommandAttrs(binding,focused,catalog.getActiveCommandView(focused)),attrs:binding.attrs,event:binding.event,preventDefault:binding.preventDefault,fallthrough:binding.fallthrough,sourceLayerOrder:binding.sourceLayerOrder,bindingIndex:binding.bindingIndex}}function emitDispatchEvent(event){if(!hooks.has("dispatch"))return;hooks.emit("dispatch",event)}function emitBindingDispatch(phase,layer,binding,focused){if(!hooks.has("dispatch"))return;emitDispatchEvent({phase,event:binding.event,focused,layer:{order:layer.order,priority:layer.priority,target:layer.target,targetMode:layer.targetMode},binding:createDispatchBinding(binding,focused),sequence:cloneKeySequence(binding.sequence),command:binding.command})}function emitSequenceDispatch(phase,captures,focused){if(!hooks.has("dispatch"))return;let first=captures[0],sequence=captures.length>0?activation.collectSequencePartsFromPending({captures}):[];emitDispatchEvent({phase,event:"press",focused,layer:first?{order:first.layer.order,priority:first.layer.priority,target:first.layer.target,targetMode:first.layer.targetMode}:void 0,sequence})}function getKeyAfterHooks(release){let hooks2=state.keyAfterHooks.entries();for(let hook of hooks2)if(hook.release===release)return hooks2;return}function getOutcomeSequence(outcome){if(outcome.sequence)return cloneKeySequence(outcome.sequence);if(outcome.captures)return activation.collectSequencePartsFromPending({captures:outcome.captures});return[]}function createSequenceOutcome(reason,captures){return{handled:reason!=="sequence-miss",reason,captures}}function createBindingOutcome(binding,handled){return{handled,reason:handled?"binding-handled":"binding-rejected",sequence:binding.sequence}}function preferDispatchOutcome(current,next){if(next.handled||current.reason==="no-match")return next;return current}function emitKeyAfter(hooks2,event,release,focused,outcome){let context={event,eventType:release?"release":"press",focused,handled:outcome.handled,reason:outcome.reason,sequence:getOutcomeSequence(outcome),pendingSequence:activation.getPendingSequence(),setData:(name,value)=>{runtime.setData(name,value)},getData:(name)=>{return runtime.getData(name)},consume:(options)=>{let shouldPreventDefault=options?.preventDefault??!0,shouldStopPropagation=options?.stopPropagation??!0;if(shouldPreventDefault)event.preventDefault();if(shouldStopPropagation)event.stopPropagation()}};for(let hook of hooks2){if(hook.release!==release)continue;try{hook.listener(context)}catch(error2){notify.emitError("key-after-intercept-error",error2,"[Keymap] Error in key:after intercept listener:")}}}function noMatchOutcome(){return{handled:!1,reason:"no-match"}}function consumeSequenceEvent(event){event.preventDefault(),event.stopPropagation()}function holdSequence(phase,captures,focused,event){activation.setPendingSequence({captures});let outcome=createSequenceOutcome("sequence-pending",captures);return emitSequenceDispatch(phase,captures,focused),consumeSequenceEvent(event),outcome}function clearSequence(reason,captures,focused,event){let outcome=createSequenceOutcome(reason,captures);return emitSequenceDispatch("sequence-clear",captures,focused),activation.setPendingSequence(null),consumeSequenceEvent(event),outcome}function handleKeyEvent(event,release){if(!release)cancelPendingDisambiguation();let afterHooks=getKeyAfterHooks(release),afterFocused=afterHooks?activation.getFocusedTarget():null,hooks2=state.keyHooks.entries(),context={event,setData:(name,value)=>{runtime.setData(name,value)},getData:(name)=>{return runtime.getData(name)},consume:(options)=>{let shouldPreventDefault=options?.preventDefault??!0,shouldStopPropagation=options?.stopPropagation??!0;if(shouldPreventDefault)event.preventDefault();if(shouldStopPropagation)event.stopPropagation()}};for(let hook of hooks2){if(hook.release!==release)continue;try{hook.listener(context)}catch(error2){notify.emitError("key-intercept-error",error2,"[Keymap] Error in key intercept listener:")}if(event.propagationStopped){if(afterHooks)emitKeyAfter(afterHooks,event,release,afterFocused,{handled:!0,reason:"intercept-consumed",sequence:[]});return}}if(release){let outcome2=dispatchReleaseLayers(event);if(afterHooks)emitKeyAfter(afterHooks,event,release,afterFocused,outcome2);return}let outcome=dispatchLayers(event);if(afterHooks)emitKeyAfter(afterHooks,event,release,afterFocused,outcome)}function mutateDisambiguationResolvers(register2,resolver){return notify.runWithStateChangeBatch(()=>{let hadResolvers=state.disambiguationResolvers.has(),off=register2();if(!hadResolvers&&state.disambiguationResolvers.has())layers.recompileBindings();return()=>{notify.runWithStateChangeBatch(()=>{let hadBeforeRemoval=state.disambiguationResolvers.has();if(off(),state.disambiguationResolvers.values().includes(resolver))return;if(hadBeforeRemoval&&!state.disambiguationResolvers.has())layers.recompileBindings()})}})}function dispatchReleaseLayers(event){let focused=activation.getFocusedTarget(),activeLayers=activation.getActiveLayers(focused),matchKeys=resolveEventMatchKeys(event),outcome=noMatchOutcome();layerLoop:for(let layer of activeLayers){if(layer.bindings.length===0)continue;if(!conditions.matchesConditions(layer))continue;for(let strokeKey of matchKeys){let result2=runReleaseBindings(layer,strokeKey,event,focused);if(outcome=preferDispatchOutcome(outcome,result2.outcome),!result2.handled)continue;if(result2.stop)return outcome;continue layerLoop}}return outcome}function dispatchLayers(event){let focused=activation.getFocusedTarget(),pending=activation.ensureValidPendingSequence(),matchKeys=resolveEventMatchKeys(event);if(pending)return dispatchPendingSequence(pending,matchKeys,event,focused);let activeLayers=activation.getActiveLayers(focused);return dispatchFromRoot(activeLayers,matchKeys,event,focused)}function dispatchPendingSequence(pending,matchKeys,event,focused){let activeView=catalog.getActiveCommandView(focused),advancedCaptures=[];for(let capture2 of pending.captures){let advanced=advanceSequenceCapture(capture2,matchKeys,event,state.patterns,matchPattern,createPatternEventPart2);if(!advanced)continue;advancedCaptures.push(advanced)}let bestPriority=advancedCaptures.reduce((best,capture2)=>Math.min(best,capturePriority(capture2,matchKeys)),Number.POSITIVE_INFINITY),prioritizedCaptures=advancedCaptures.filter((capture2)=>capturePriority(capture2,matchKeys)===bestPriority);if(prioritizedCaptures.length===0||!prioritizedCaptures.some((capture2)=>captureIsReachable(capture2,focused,activeView))){let outcome=createSequenceOutcome("sequence-miss",pending.captures);return emitSequenceDispatch("sequence-clear",pending.captures,focused),activation.setPendingSequence(null),outcome}return dispatchPendingCapturesFromIndex(prioritizedCaptures,0,!1,event,focused)}function dispatchPendingCapturesFromIndex(advancedCaptures,startIndex,handledExact,event,focused){let hasHandledExact=handledExact,outcome=noMatchOutcome(),processedExact=new Set;for(let index=startIndex;index<advancedCaptures.length;index+=1){let capture2=advancedCaptures[index];if(!capture2||processedExact.has(capture2))continue;let continuationCapturesForPrefix=collectContinuationCapturesForPrefix(advancedCaptures,index,capture2);if(continuationCapturesForPrefix.length>0){if(hasHandledExact)continue;let exactCaptures2=collectExactCapturesForPrefix(advancedCaptures,capture2),resolvedOutcome=tryResolvePendingAmbiguity(advancedCaptures,index,continuationCapturesForPrefix,exactCaptures2,event,focused,hasHandledExact);if(resolvedOutcome)return resolvedOutcome;return holdSequence("sequence-advance",continuationCapturesForPrefix,focused,event)}if(!captureIsExact(capture2,state.patterns))continue;let exactCaptures=collectExactCapturesForPrefix(advancedCaptures,capture2);for(let exact of exactCaptures)processedExact.add(exact);let result2=runCaptureBindings(capture2.layer,exactCaptures,event,focused);if(outcome=preferDispatchOutcome(outcome,result2.outcome),!result2.handled)continue;if(hasHandledExact=!0,result2.stop)return emitSequenceDispatch("sequence-clear",advancedCaptures,focused),activation.setPendingSequence(null),outcome}return emitSequenceDispatch("sequence-clear",advancedCaptures,focused),activation.setPendingSequence(null),outcome}function dispatchFromRoot(activeLayers,matchKeys,event,focused){return dispatchFromRootAtIndex(activeLayers,0,matchKeys,event,focused)}function dispatchFromRootAtIndex(activeLayers,startIndex,matchKeys,event,focused){let activeView=catalog.getActiveCommandView(focused),outcome=noMatchOutcome();for(let index=startIndex;index<activeLayers.length;index+=1){let layer=activeLayers[index];if(!layer)continue;if(!conditions.matchesConditions(layer))continue;let captures=collectRootCaptures(layer,matchKeys,event,focused,activeView);if(captures.length===0)continue;if(captures.filter((capture2)=>captureHasContinuations(capture2,state.patterns,!1)).length>0){let exactCaptures2=captures.filter((capture2)=>captureIsExact(capture2,state.patterns)),continuationCaptures=collectPendingCapturesFromRoot(activeLayers,index,matchKeys,event,focused),resolvedOutcome=tryResolveRootAmbiguity(activeLayers,index,matchKeys,continuationCaptures,exactCaptures2,event,focused);if(resolvedOutcome)return resolvedOutcome;return holdSequence("sequence-start",continuationCaptures,focused,event)}let exactCaptures=captures.filter((capture2)=>captureIsExact(capture2,state.patterns)),result2=runCaptureBindings(layer,exactCaptures,event,focused);if(outcome=preferDispatchOutcome(outcome,result2.outcome),!result2.handled)continue;if(result2.stop)return outcome}return outcome}function tryResolveRootAmbiguity(activeLayers,layerIndex,matchKeys,continuationCaptures,exactCaptures,event,focused){let applyExact=()=>{activation.setPendingSequence(null);let layer=exactCaptures[0]?.layer;if(!layer)return noMatchOutcome();let result2=runCaptureBindings(layer,exactCaptures,event,focused);if(!result2.stop)return preferDispatchOutcome(result2.outcome,dispatchFromRootAtIndex(activeLayers,layerIndex+1,matchKeys,event,focused));return result2.outcome};return tryResolveAmbiguity({event,focused,continuationCaptures,exactBindingsSource:exactCaptures.map((capture2)=>capture2.binding),sequencePhase:"sequence-start",runExact:applyExact})}function tryResolvePendingAmbiguity(advancedCaptures,captureIndex,continuationCaptures,exactCaptures,event,focused,handledExact){let applyExact=()=>{activation.setPendingSequence(null);let layer=exactCaptures[0]?.layer;if(!layer)return noMatchOutcome();let result2=runCaptureBindings(layer,exactCaptures,event,focused);if(result2.stop)return result2.outcome;return preferDispatchOutcome(result2.outcome,dispatchPendingCapturesFromIndex(advancedCaptures,captureIndex+1,handledExact||result2.handled,event,focused))};return tryResolveAmbiguity({event,focused,continuationCaptures,exactBindingsSource:exactCaptures.map((capture2)=>capture2.binding),sequencePhase:"sequence-advance",runExact:applyExact})}function tryResolveAmbiguity(options){let{event,focused,continuationCaptures,exactBindingsSource,sequencePhase,runExact}=options;if(!state.disambiguationResolvers.has()||continuationCaptures.length===0)return;let activeView=catalog.getActiveCommandView(focused),exactBindings=activation.collectMatchingBindings(exactBindingsSource,focused,activeView);if(!exactBindings.some((binding)=>binding.command!==void 0))return;let continueSequence=()=>{return holdSequence(sequencePhase,continuationCaptures,focused,event)},clear=()=>{return clearSequence("sequence-cleared",continuationCaptures,focused,event)},sequence,getSequence=()=>{return sequence??=activation.collectSequencePartsFromPending({captures:continuationCaptures}),sequence},decision=resolveDisambiguation({event,focused,getSequence,exactBindings,continuationCaptures,activeView});if(!decision)return warnUnresolvedAmbiguity(getSequence()),continueSequence();return applySyncDecision(decision,continuationCaptures,runExact,continueSequence,clear,focused,getSequence)}function applySyncDecision(decision,continuationCaptures,runExact,continueSequence,clear,focused,getSequence){if(decision.action==="run-exact")return runExact();if(decision.action==="continue-sequence")return continueSequence();if(decision.action==="clear")return clear();let outcome=continueSequence();return scheduleDeferredDisambiguation(continuationCaptures,decision.handler,focused,getSequence(),(nextDecision)=>{if(!nextDecision)return;if(nextDecision.action==="run-exact"){runExact();return}if(nextDecision.action==="continue-sequence"){continueSequence();return}clear()}),outcome}function resolveDisambiguation(options){let sequence,exact,continuations,strokePart,ctx={event:options.event,focused:options.focused,get sequence(){return sequence??=cloneKeySequence(options.getSequence()),sequence},get stroke(){let stroke=options.getSequence().at(-1);if(!stroke)throw Error("Disambiguation context expected a non-empty sequence");return strokePart??={...stroke,stroke:cloneKeyStroke(stroke.stroke)},strokePart},get exact(){return exact??=activation.collectActiveBindings(options.exactBindings,options.focused,options.activeView).map((binding)=>({...binding,sequence:cloneKeySequence(binding.sequence)})),exact},get continuations(){return continuations??=activation.getActiveKeysForCaptures(options.continuationCaptures,{includeBindings:!0,includeMetadata:!0}),continuations},getData:(name)=>{return runtime.getData(name)},setData:(name,value)=>{runtime.setData(name,value)},runExact:()=>createSyncDecision("run-exact"),continueSequence:()=>createSyncDecision("continue-sequence"),clear:()=>createSyncDecision("clear"),defer:(run)=>createSyncDecision("defer",run)};for(let resolver of state.disambiguationResolvers.values()){let result2;try{result2=resolver(ctx)}catch(error2){notify.emitError("disambiguation-resolver-error",error2,"[Keymap] Error in disambiguation resolver:");continue}if(result2===void 0)continue;if(isPromiseLike(result2)){notify.emitError("invalid-disambiguation-resolver-return",result2,"[Keymap] Disambiguation resolvers must return synchronously; use ctx.defer(...) for async handling");continue}if(!isSyncDecision(result2)){notify.emitError("invalid-disambiguation-decision",result2,"[Keymap] Invalid disambiguation decision returned by resolver:");continue}return result2}return}function scheduleDeferredDisambiguation(captures,handler,focused,sequence,apply){cancelPendingDisambiguation();let controller=new AbortController,pending={id:nextPendingDisambiguationId++,controller,captures,apply};pendingDisambiguation=pending,queueMicrotask(()=>{executeDeferredDisambiguation(pending,handler,focused,sequence)})}function executeDeferredDisambiguation(pending,handler,focused,sequence){if(!isPendingDisambiguationCurrent(pending))return;let ctx={signal:pending.controller.signal,sequence:cloneKeySequence(sequence),focused,sleep:(ms)=>{return sleepWithSignal(ms,pending.controller.signal)},runExact:()=>createDeferredDecision("run-exact"),continueSequence:()=>createDeferredDecision("continue-sequence"),clear:()=>createDeferredDecision("clear")},result2;try{result2=handler(ctx)}catch(error2){if(isPendingDisambiguationCurrent(pending))notify.emitError("deferred-disambiguation-error",error2,"[Keymap] Error in deferred disambiguation handler:"),finishPendingDisambiguation(pending);return}if(isPromiseLike(result2)){result2.then((resolved)=>{applyDeferredDisambiguationResult(pending,resolved)}).catch((error2)=>{if(!isPendingDisambiguationCurrent(pending))return;notify.emitError("deferred-disambiguation-error",error2,"[Keymap] Error in deferred disambiguation handler:"),finishPendingDisambiguation(pending)});return}applyDeferredDisambiguationResult(pending,result2)}function applyDeferredDisambiguationResult(pending,result2){if(!isPendingDisambiguationCurrent(pending))return;if(result2!==void 0&&!isDeferredDecision(result2)){notify.emitError("invalid-deferred-disambiguation-decision",result2,"[Keymap] Invalid deferred disambiguation decision returned by handler:"),finishPendingDisambiguation(pending);return}finishPendingDisambiguation(pending),pending.apply(result2)}function finishPendingDisambiguation(pending){if(!isPendingDisambiguationCurrent(pending))return;pendingDisambiguation=null}function cancelPendingDisambiguation(){let pending=pendingDisambiguation;if(!pending)return;pendingDisambiguation=null,pending.controller.abort()}function isPendingDisambiguationCurrent(pending){return pendingDisambiguation===pending}function warnUnresolvedAmbiguity(sequence){let display=stringifyKeySequence(sequence,{preferDisplay:!0});notify.warnOnce(`unresolved-disambiguation:${display}`,"unresolved-disambiguation",{sequence:display},`[Keymap] Ambiguous exact/prefix sequence "${display}" fell back to prefix handling because no disambiguation resolver resolved it`)}function collectPendingCapturesFromRoot(activeLayers,startIndex,matchKeys,event,focused){let captures=[],activeView=catalog.getActiveCommandView(focused);for(let index=startIndex;index<activeLayers.length;index+=1){let layer=activeLayers[index];if(!layer)continue;if(!conditions.matchesConditions(layer))continue;for(let capture2 of collectRootCaptures(layer,matchKeys,event,focused,activeView))if(captureHasContinuations(capture2,state.patterns,!1))captures.push(capture2)}return captures}function collectContinuationCapturesForPrefix(captures,startIndex,prefix){return captures.filter((candidate,candidateIndex)=>{return candidateIndex>=startIndex&&captureHasContinuations(candidate,state.patterns,!1)&&sameParts(candidate.parts,prefix.parts)})}function collectExactCapturesForPrefix(captures,prefix){return captures.filter((capture2)=>{return capture2.layer===prefix.layer&&captureIsExact(capture2,state.patterns)&&sameParts(capture2.parts,prefix.parts)})}function resolveEventMatchKeys(event){let resolvers=state.eventMatchResolvers.values();if(resolvers.length===0)return[];if(resolvers.length===1)return resolveSingleEventMatchKeys(resolvers[0],event,eventMatchResolverContext,notify);let keys=[],seen=new Set;for(let resolver of resolvers){let resolved;try{resolved=resolver(event,eventMatchResolverContext)}catch(error2){notify.emitError("event-match-resolver-error",error2,"[Keymap] Error in event match resolver:");continue}if(!resolved||resolved.length===0)continue;for(let candidate of resolved){if(typeof candidate!=="string"){notify.emitError("invalid-event-match-resolver-candidate",candidate,"[Keymap] Invalid event match resolver candidate:");continue}if(seen.has(candidate))continue;seen.add(candidate),keys.push(candidate)}}return keys}function runReleaseBindings(layer,strokeKey,event,focused){let handled=!1,outcome=noMatchOutcome();for(let binding of layer.bindings){if(binding.event!=="release")continue;let firstPart=binding.sequence[0];if(!firstPart||firstPart.match!==strokeKey)continue;if(!conditions.matchesConditions(binding))continue;let bindingHandled=executor.runBinding(layer,binding,event,focused);if(outcome=preferDispatchOutcome(outcome,createBindingOutcome(binding,bindingHandled)),!bindingHandled){emitBindingDispatch("binding-reject",layer,binding,focused);continue}if(emitBindingDispatch("binding-execute",layer,binding,focused),handled=!0,!binding.fallthrough)return{handled:!0,stop:!0,outcome}}return{handled,stop:!1,outcome}}function matchPattern(patternName,event){return matchSequencePattern(state.patterns,notify,patternName,event)}function createPatternEventPart2(event,patternName,match){return createPatternEventPart(state.patterns,event,patternName,match)}function collectRootCaptures(layer,matchKeys,event,focused,activeView){let captures=collectRootSequenceCaptures(layer,matchKeys,event,matchPattern,createPatternEventPart2);return captures.some((capture2)=>captureIsReachable(capture2,focused,activeView))?captures:[]}function createSequencePayload2(capture2){return createSequencePayload(state.patterns,notify,capture2)}function bindingMatchesRuntimeState(binding,focused,activeView){return conditions.matchesConditions(binding)&&catalog.isBindingVisible(binding,focused,activeView)}function captureIsReachable(capture2,focused,activeView){return bindingMatchesRuntimeState(capture2.binding,focused,activeView)}function runCaptureBindings(layer,captures,event,focused){let handled=!1,outcome=noMatchOutcome();for(let capture2 of captures){let binding=capture2.binding;if(!conditions.matchesConditions(binding))continue;let bindingHandled=executor.runBinding(layer,binding,event,focused,createSequencePayload2(capture2));if(outcome=preferDispatchOutcome(outcome,createBindingOutcome(binding,bindingHandled)),!bindingHandled){emitBindingDispatch("binding-reject",layer,binding,focused);continue}if(emitBindingDispatch("binding-execute",layer,binding,focused),handled=!0,!binding.fallthrough)return{handled:!0,stop:!0,outcome}}return{handled,stop:!1,outcome}}return{intercept,prependEventMatchResolver,appendEventMatchResolver,clearEventMatchResolvers,prependDisambiguationResolver,appendDisambiguationResolver,clearDisambiguationResolvers,handlePendingSequenceChange,handleRawSequence,handleKeyEvent}}function resolveSingleEventMatchKeys(resolver,event,ctx,notify){let resolved;try{resolved=resolver(event,ctx)}catch(error2){return notify.emitError("event-match-resolver-error",error2,"[Keymap] Error in event match resolver:"),[]}if(!resolved||resolved.length===0)return[];if(resolved.length===1){let[candidate]=resolved;if(typeof candidate!=="string")return notify.emitError("invalid-event-match-resolver-candidate",candidate,"[Keymap] Invalid event match resolver candidate:"),[];return[candidate]}let keys=[],seen=new Set;for(let candidate of resolved){if(typeof candidate!=="string"){notify.emitError("invalid-event-match-resolver-candidate",candidate,"[Keymap] Invalid event match resolver candidate:");continue}if(seen.has(candidate))continue;seen.add(candidate),keys.push(candidate)}return keys}function sameParts(left,right){if(left.length!==right.length)return!1;for(let index=0;index<left.length;index+=1)if(left[index]?.match!==right[index]?.match)return!1;return!0}function normalizePatternLimit(name,field,value,fallback){if(value===void 0)return fallback;if(typeof value!=="number"||!Number.isInteger(value)||value<0)throw Error(`Keymap sequence pattern "${name}" ${field} must be a non-negative integer`);return value}function registerFieldCompilers(fields,options){let{kind,reservedFields,registeredFields,emitError}=options,entries=Object.entries(fields),registered=[];for(let[name,compiler]of entries){if(reservedFields.has(name)){emitError(`reserved-${kind}-field`,{field:name,kind},`Keymap ${kind} field "${name}" is reserved`);continue}if(registeredFields.has(name)){emitError(`duplicate-${kind}-field`,{field:name,kind},`Keymap ${kind} field "${name}" is already registered`);continue}registeredFields.set(name,compiler),registered.push([name,compiler])}return()=>{for(let[name,compiler]of registered)if(registeredFields.get(name)===compiler)registeredFields.delete(name)}}function registerToken(state,notify,compiler,layers,token){let normalizedToken;try{normalizedToken=normalizeBindingTokenName(token.name)}catch(error2){return notify.emitError("token-name-normalize-error",error2,getErrorMessage(error2,"Failed to register keymap token")),NOOP}if(state.tokens.has(normalizedToken)||state.patterns.has(normalizedToken))return notify.emitError("duplicate-token",{token:normalizedToken},`Keymap token "${normalizedToken}" is already registered`),NOOP;let parsedToken;try{if(parsedToken=compiler.parseTokenKey(token.key),parsedToken.patternName)throw Error(`Invalid key "${String(token.key)}": expected a concrete key stroke`)}catch(error2){return notify.emitError("token-parse-error",error2,getErrorMessage(error2,`Failed to register keymap token "${normalizedToken}"`)),NOOP}let registeredToken={stroke:parsedToken.stroke,match:parsedToken.match},nextTokens=new Map(state.tokens);nextTokens.set(normalizedToken,registeredToken);try{layers.applyTokenState(nextTokens)}catch(error2){return notify.emitError("token-register-error",error2,getErrorMessage(error2,`Failed to register keymap token "${normalizedToken}"`)),NOOP}return()=>{if(state.tokens.get(normalizedToken)!==registeredToken)return;let nextTokens2=new Map(state.tokens);nextTokens2.delete(normalizedToken);try{layers.applyTokenState(nextTokens2)}catch(error2){notify.emitError("token-unregister-error",error2,getErrorMessage(error2,`Failed to unregister keymap token "${normalizedToken}"`))}}}function registerSequencePattern(state,notify,layers,pattern){let normalizedName,resolvedPattern;try{normalizedName=normalizeBindingTokenName(pattern.name);let min=normalizePatternLimit(normalizedName,"min",pattern.min,1),max=normalizePatternLimit(normalizedName,"max",pattern.max,Number.MAX_SAFE_INTEGER);if(max<min)throw Error(`Keymap sequence pattern "${normalizedName}" max must be greater than or equal to min`);resolvedPattern={name:normalizedName,display:pattern.display,payloadKey:pattern.payloadKey??normalizedName,match:createTextKeyMatch(`pattern:${normalizedName}`),min,max,matcher:(event)=>pattern.match(event),finalize:pattern.finalize}}catch(error2){return notify.emitError("sequence-pattern-register-error",error2,getErrorMessage(error2,"Failed to register keymap sequence pattern")),NOOP}if(state.tokens.has(normalizedName)||state.patterns.has(normalizedName))return notify.emitError("duplicate-sequence-pattern",{pattern:normalizedName},`Keymap sequence pattern "${normalizedName}" is already registered`),NOOP;return state.patterns.set(normalizedName,resolvedPattern),layers.recompileBindings(),()=>{if(state.patterns.get(normalizedName)!==resolvedPattern)return;state.patterns.delete(normalizedName),layers.recompileBindings()}}function registerFields(state,notify,kind,fields){let reservedFields=kind==="layer"?RESERVED_LAYER_FIELDS:kind==="binding"?RESERVED_BINDING_FIELDS:RESERVED_COMMAND_FIELDS,registeredFields=kind==="layer"?state.layerFields:kind==="binding"?state.bindingFields:state.commandFields;return registerFieldCompilers(fields,{kind,reservedFields,registeredFields,emitError:(code,error2,message)=>notify.emitError(code,error2,message)})}function compareLayers(left,right){return right.priority-left.priority||right.order-left.order}function layerBlocksActiveKeyCache(layer){if(layer.matchers.length>0)return!0;for(let command of layer.commands)if(command.matchers.length>0)return!0;for(let binding of layer.bindings)if(binding.matchers.length>0)return!0;return!1}function layerBlocksActiveCommandViewCache(layer){if(layer.commands.length===0)return!1;if(layer.matchers.length>0)return!0;for(let command of layer.commands)if(command.matchers.length>0)return!0;return!1}function createLayerService(state,notify,conditions,activation,options){let registerLayer=(layer)=>{return notify.runWithStateChangeBatch(()=>{let target=layer.target;if(target&&options.host.isTargetDestroyed(target))return notify.emitError("destroyed-layer-target",{target},"Cannot register a keymap layer for a destroyed keymap target"),NOOP2;let sourceBindings,requires,matchers,fields,attrs,commands,targetMode;try{targetMode=normalizeTargetMode(layer),sourceBindings=applyLayerBindingsTransformers(snapshotBindings(layer.bindings??[]),layer);let sourceCommands=applyCommandTransformers(layer.commands??[],layer);commands=sourceCommands.length===0?[]:options.commands.normalizeCommands(sourceCommands),{requires,matchers,fields,attrs}=compileLayerRuntimeState(layer)}catch(error2){return notify.emitError("register-layer-failed",error2,getErrorMessage(error2,"Failed to register keymap layer")),NOOP2}let order=state.order++,bindingStates=options.compiler.compileBindings(sourceBindings,state.tokens,target,order,fields);if(bindingStates.bindings.length===0&&!bindingStates.hasTokenBindings&&commands.length===0)return NOOP2;options.diagnostics?.analyzeLayer({target,order,commands,sourceBindings,bindings:bindingStates.bindings,hasTokenBindings:bindingStates.hasTokenBindings});let registeredLayer={order,target,targetMode,priority:layer.priority??0,requires,matchers,fields,attrs,commands,sourceBindings,bindings:bindingStates.bindings,root:buildSequenceTree(bindingStates.bindings,state.patterns),hasTokenBindings:bindingStates.hasTokenBindings,activeKeyCacheBlocked:!1,activeCommandViewCacheBlocked:!1};updateCacheBlockers(registeredLayer),state.layers.add(registeredLayer),state.sortedLayers=[...state.sortedLayers,registeredLayer].sort(compareLayers),attachReactiveMatchers(registeredLayer);for(let command of registeredLayer.commands)attachReactiveMatchers(command);for(let binding of registeredLayer.bindings)attachReactiveMatchers(binding);if(target){let onTargetDestroy=()=>{unregisterLayer(registeredLayer)};registeredLayer.offTargetDestroy=options.host.onTargetDestroy(target,onTargetDestroy)}if(registeredLayer.commands.length>0)activation.ensureValidPendingSequence();return notify.queueStateChange(),()=>{unregisterLayer(registeredLayer)}})},applyTokenState=(nextTokens)=>{notify.runWithStateChangeBatch(()=>{let nextCompilations=new Map;for(let layer of state.layers){if(!layer.hasTokenBindings)continue;nextCompilations.set(layer,compileLayerBindings(layer,nextTokens))}state.tokens=nextTokens;let shouldClearPending=!1;for(let[layer,compilation]of nextCompilations)if(applyBindingStates(layer,compilation))shouldClearPending=!0;if(shouldClearPending)activation.setPendingSequence(null);if(nextCompilations.size>0)notify.queueStateChange()})},recompileBindings=()=>{notify.runWithStateChangeBatch(()=>{let recompiledLayers=0,shouldClearPending=!1;for(let layer of state.layers){if(layer.sourceBindings.length===0)continue;let compilation=compileLayerBindings(layer,state.tokens);if(applyBindingStates(layer,compilation))shouldClearPending=!0;recompiledLayers+=1}if(shouldClearPending)activation.setPendingSequence(null);if(recompiledLayers>0)notify.queueStateChange()})},cleanup=()=>{for(let layer of state.layers){detachReactiveMatchers(layer);for(let command of layer.commands)detachReactiveMatchers(command);for(let binding of layer.bindings)detachReactiveMatchers(binding);layer.offTargetDestroy?.(),layer.offTargetDestroy=void 0}},normalizeTargetMode=(layer)=>{if(layer.targetMode){if(!layer.target)throw Error(`Keymap targetMode "${layer.targetMode}" requires a target`);return layer.targetMode}return layer.target?"focus-within":void 0},applyLayerBindingsTransformers=(bindings,layer)=>{let transformers=state.layerBindingsTransformers.values();if(transformers.length===0)return bindings;let current=bindings;for(let transformer of transformers){let next=transformer(current,{layer,validateBindings:(bindings2)=>validateBindings(bindings2)});if(!next)continue;current=snapshotBindings(next)}return current},applyCommandTransformers=(commands,layer)=>{let transformers=state.commandTransformers.values();if(commands.length===0||transformers.length===0)return commands;let transformedCommands=[];for(let command of commands){let transformedCommand={...command},extraCommands=[],keepOriginal=!0;for(let transformer of transformers)try{transformer(transformedCommand,{layer,add(nextCommand){extraCommands.push({...nextCommand})},skipOriginal(){keepOriginal=!1}})}catch(error2){notify.emitError("command-transformer-error",error2,"[Keymap] Error in command transformer:")}if(keepOriginal)transformedCommands.push(transformedCommand);transformedCommands.push(...extraCommands)}return transformedCommands},compileLayerRuntimeState=(layer)=>{let mergedRequires={},matchers=[],fields=Object.create(null),attrs={};for(let[fieldName,value]of Object.entries(layer)){if(RESERVED_LAYER_FIELDS.has(fieldName))continue;if(value===void 0)continue;fields[fieldName]=snapshotDataValue(value);let compiler=state.layerFields.get(fieldName);if(!compiler){options.warnUnknownField("layer",fieldName);continue}compiler(value,createFieldCompilerContext({fieldName,conditions,requirements:mergedRequires,matchers,attrs}))}return{requires:Object.entries(mergedRequires),matchers,fields:Object.keys(fields).length>0?Object.freeze(fields):void 0,attrs:Object.keys(attrs).length>0?snapshotDataValue(attrs,{freeze:!0}):void 0}},compileLayerBindings=(layer,tokens2)=>{return options.compiler.compileBindings(layer.sourceBindings,tokens2,layer.target,layer.order,layer.fields)},applyBindingStates=(layer,compilation)=>{options.diagnostics?.analyzeLayer({target:layer.target,order:layer.order,commands:layer.commands,sourceBindings:layer.sourceBindings,bindings:compilation.bindings,hasTokenBindings:compilation.hasTokenBindings}),untrackCacheBlockers(layer);for(let binding of layer.bindings)detachReactiveMatchers(binding);layer.bindings=compilation.bindings,layer.root=buildSequenceTree(compilation.bindings,state.patterns),layer.hasTokenBindings=compilation.hasTokenBindings,updateCacheBlockers(layer);for(let binding of layer.bindings)attachReactiveMatchers(binding);return state.pending?.captures.some((capture2)=>capture2.layer===layer)??!1},unregisterLayer=(layer)=>{notify.runWithStateChangeBatch(()=>{if(!state.layers.delete(layer))return;state.sortedLayers=state.sortedLayers.filter((candidate)=>candidate!==layer),untrackCacheBlockers(layer),detachReactiveMatchers(layer);for(let command of layer.commands)detachReactiveMatchers(command);for(let binding of layer.bindings)detachReactiveMatchers(binding);if(layer.offTargetDestroy?.(),layer.offTargetDestroy=void 0,state.pending?.captures.some((capture2)=>capture2.layer===layer))activation.setPendingSequence(null);else if(layer.commands.length>0&&!options.host.isDestroyed)activation.ensureValidPendingSequence();notify.queueStateChange()})},attachReactiveMatchers=(target)=>{for(let matcher of target.matchers){if(!matcher.subscribe)continue;try{matcher.dispose=matcher.subscribe(()=>{if(!activation.hasPendingSequenceState()){notify.queueStateChange();return}notify.runWithStateChangeBatch(()=>{activation.revalidatePendingSequenceIfNeeded(),notify.queueStateChange()})})}catch(error2){notify.emitError("reactive-matcher-subscribe-error",error2,getErrorMessage(error2,`Failed to subscribe to reactive matcher from ${matcher.source}`))}}},updateCacheBlockers=(layer)=>{let activeKeyBlocked=layerBlocksActiveKeyCache(layer),activeCommandViewBlocked=layerBlocksActiveCommandViewCache(layer);if(layer.activeKeyCacheBlocked=activeKeyBlocked,layer.activeCommandViewCacheBlocked=activeCommandViewBlocked,activeKeyBlocked)state.activeKeyCacheBlockers+=1;if(activeCommandViewBlocked)state.activeCommandViewCacheBlockers+=1},untrackCacheBlockers=(layer)=>{if(layer.activeKeyCacheBlocked)state.activeKeyCacheBlockers-=1,layer.activeKeyCacheBlocked=!1;if(layer.activeCommandViewCacheBlocked)state.activeCommandViewCacheBlockers-=1,layer.activeCommandViewCacheBlocked=!1},detachReactiveMatchers=(target)=>{for(let matcher of target.matchers){if(!matcher.dispose)continue;try{matcher.dispose()}catch(error2){notify.emitError("reactive-matcher-dispose-error",error2,getErrorMessage(error2,`Failed to dispose reactive matcher from ${matcher.source}`))}matcher.dispose=void 0}};return{registerLayer,applyTokenState,recompileBindings,cleanup}}function createNotificationService(state,events,hooks){let emitWarning=(code,warning,message)=>{if(!events.has("warning")){let consoleMessage=`[${code}] ${message}`;if(warning instanceof Error)console.warn(consoleMessage,warning);else console.warn(consoleMessage);return}events.emit("warning",{code,message,warning})},emitError=(code,error2,message)=>{if(!events.has("error")){let consoleMessage=`[${code}] ${message}`;if(error2 instanceof Error)console.error(consoleMessage,error2);else console.error(consoleMessage);return}events.emit("error",{code,message,error:error2})},flushStateChange=()=>{if(!state.stateChangePending||state.stateChangeDepth>0||state.flushingStateChange)return;state.flushingStateChange=!0;try{let iterations=0;while(state.stateChangePending&&state.stateChangeDepth===0){if(iterations>=MAX_STATE_CHANGE_FLUSH_ITERATIONS){state.stateChangePending=!1,emitError("state-change-feedback-loop",{iterations:MAX_STATE_CHANGE_FLUSH_ITERATIONS},`[Keymap] Possible infinite state listener feedback loop detected after ${MAX_STATE_CHANGE_FLUSH_ITERATIONS} iterations; pending state notifications were dropped`);break}iterations+=1,state.stateChangePending=!1,hooks.emit("state")}}finally{state.flushingStateChange=!1}};return{runWithStateChangeBatch(fn){state.stateChangeDepth+=1;try{return fn()}finally{if(state.stateChangeDepth-=1,state.stateChangeDepth===0)flushStateChange()}},queueStateChange(options){if(state.derivedVersion+=1,options?.invalidateCaches!==!1)state.cacheVersion+=1;if(!hooks.has("state"))return;if(state.stateChangePending=!0,state.stateChangeDepth===0&&!state.flushingStateChange)flushStateChange()},emitWarning,emitError,reportListenerError(name,error2){if(name==="state"){emitError("state-listener-error",error2,"[Keymap] Error in state listener:");return}if(name==="pendingSequence"){emitError("pending-sequence-listener-error",error2,"[Keymap] Error in pending sequence listener:");return}if(name==="dispatch")emitError("dispatch-listener-error",error2,"[Keymap] Error in dispatch listener:")},warnOnce(key,code,warning,message){if(state.usedWarningKeys.has(key))return;state.usedWarningKeys.add(key),emitWarning(code,warning,message)}}}function createRuntimeService(state,notify,activation){return{getData(name){return state.data[name]},setData(name,value){notify.runWithStateChangeBatch(()=>{if(value===void 0){if(!(name in state.data))return;delete state.data[name],state.dataVersion+=1,activation.ensureValidPendingSequence(),notify.queueStateChange();return}if(Object.is(state.data[name],value))return;state.data[name]=value,state.dataVersion+=1,activation.ensureValidPendingSequence(),notify.queueStateChange()})},getReadonlyData(){if(state.readonlyDataVersion===state.dataVersion)return state.readonlyData;return state.readonlyData=Object.freeze({...state.data}),state.readonlyDataVersion=state.dataVersion,state.readonlyData}}}function createKeymapState(){return{order:0,tokens:new Map,patterns:new Map,layerFields:new Map,layerBindingsTransformers:createRuntimeOrderedRegistry(),bindingExpanders:createRuntimeOrderedRegistry(),bindingParsers:createRuntimeOrderedRegistry(),bindingTransformers:createRuntimeOrderedRegistry(),bindingFields:new Map,commandTransformers:createRuntimeOrderedRegistry(),commandFields:new Map,eventMatchResolvers:createRuntimeOrderedRegistry(),disambiguationResolvers:createRuntimeOrderedRegistry(),keyHooks:createRuntimePriorityRegistry(),keyAfterHooks:createRuntimePriorityRegistry(),rawHooks:createRuntimePriorityRegistry(),layers:new Set,sortedLayers:[],activeLayersCacheVersion:-1,activeLayersCacheFocused:void 0,activeLayersCache:[],activeKeyCacheBlockers:0,activeCommandViewCacheBlockers:0,commandResolvers:createRuntimeOrderedRegistry(),pending:null,data:{},dataVersion:0,readonlyDataVersion:-1,readonlyData:EMPTY_DATA,cacheVersion:0,derivedVersion:0,stateChangeDepth:0,stateChangePending:!1,flushingStateChange:!1,usedWarningKeys:new Set}}function getKeyMatchKey(input){return resolveKeyMatch(input)}var RESERVED_COMMAND_FIELDS,RESERVED_BINDING_FIELDS,RESERVED_LAYER_FIELDS,DEFAULT_COMMAND_SEARCH_FIELDS,EMPTY_COMMAND_FIELDS,commandSearchCache,EMPTY_COMPILE_FIELDS,EMPTY_REQUIRES,EMPTY_MATCHERS,KEY_DISAMBIGUATION_DECISION,KEY_DEFERRED_DISAMBIGUATION_DECISION,NOOP=()=>{},NOOP2=()=>{},MAX_STATE_CHANGE_FLUSH_ITERATIONS=1000,EMPTY_DATA,Keymap;var init_src2=__esm(()=>{init_index_frk6sdcd();RESERVED_COMMAND_FIELDS=new Set(["name","run","fields","attrs","rejectedResult"]),RESERVED_BINDING_FIELDS=new Set(["key","cmd","event","preventDefault","fallthrough"]),RESERVED_LAYER_FIELDS=new Set(["target","targetMode","priority","bindings","commands"]);DEFAULT_COMMAND_SEARCH_FIELDS=["name"],EMPTY_COMMAND_FIELDS=Object.freeze({}),commandSearchCache=new WeakMap;EMPTY_COMPILE_FIELDS=Object.freeze({}),EMPTY_REQUIRES=[],EMPTY_MATCHERS=[];KEY_DISAMBIGUATION_DECISION=Symbol("keymap-disambiguation-decision"),KEY_DEFERRED_DISAMBIGUATION_DECISION=Symbol("keymap-deferred-disambiguation-decision");EMPTY_DATA=Object.freeze({});Keymap=class Keymap{#state=createKeymapState();#cleanedUp=!1;#resources=new Map;#cleanupListeners=[];#events=createRuntimeEmitter(()=>{});#hooks;#notify;#activation;#runtime;#conditions;#catalog;#executor;#compiler;#dispatch;#layers;#layerDiagnostics;#keypressListener;#keyreleaseListener;#rawListener;#focusedTargetListener;#host;getPendingSequence;getActiveKeys;constructor(host){if(this.#host=host,host.isDestroyed)throw Error("Cannot create a keymap for a destroyed host");if(this.#hooks=createRuntimeEmitter((name,error2)=>{this.#notify.reportListenerError(name,error2)}),this.#notify=createNotificationService(this.#state,this.#events,this.#hooks),this.#conditions=createConditionService(this.#state,this.#notify),this.#catalog=createCommandCatalogService(this.#state,this.#host,this.#notify,this.#conditions,{onCommandResolversChanged:()=>{this.#activation.ensureValidPendingSequence()}}),this.#activation=createActivationService(this.#state,this.#host,this.#hooks,this.#notify,this.#conditions,this.#catalog,{onPendingSequenceChanged:(previous,next)=>{this.#dispatch?.handlePendingSequenceChange(previous,next)}}),this.#runtime=createRuntimeService(this.#state,this.#notify,this.#activation),this.#executor=createCommandExecutorService(this.#notify,this.#runtime,this.#activation,this.#catalog,{keymap:this,createCommandEvent:()=>this.#host.createCommandEvent()}),this.#compiler=createCompilerService(this.#state,this.#notify,this.#conditions,{warnUnknownField:(kind,fieldName)=>{this.#warnUnknownField(kind,fieldName)},warnUnknownToken:(token,sequence)=>{this.#warnUnknownToken(token,sequence)}}),this.#layerDiagnostics=createLayerDiagnostics(this.#notify,this.#catalog),this.#layers=createLayerService(this.#state,this.#notify,this.#conditions,this.#activation,{compiler:this.#compiler,commands:this.#catalog,host:this.#host,diagnostics:this.#layerDiagnostics,warnUnknownField:(kind,fieldName)=>{this.#warnUnknownField(kind,fieldName)}}),this.#dispatch=createDispatchService(this.#state,this.#notify,this.#runtime,this.#activation,this.#conditions,this.#executor,this.#compiler,this.#catalog,this.#layers,this.#hooks),this.getPendingSequence=this.#activation.getPendingSequence,this.getActiveKeys=this.#activation.getActiveKeys,this.#keypressListener=(event)=>{this.#dispatch.handleKeyEvent(event,!1)},this.#keyreleaseListener=(event)=>{this.#dispatch.handleKeyEvent(event,!0)},this.#rawListener=(sequence)=>{return this.#dispatch.handleRawSequence(sequence)},this.#focusedTargetListener=(focused)=>{this.#handleFocusedTargetChange(focused)},this.#cleanupListeners.push(this.#host.onKeyPress(this.#keypressListener)),this.#cleanupListeners.push(this.#host.onKeyRelease(this.#keyreleaseListener)),this.#host.onRawInput)this.#cleanupListeners.push(this.#host.onRawInput(this.#rawListener));if(this.#cleanupListeners.push(this.#host.onFocusChange(this.#focusedTargetListener)),this.#host.onDestroy)this.#cleanupListeners.push(this.#host.onDestroy(()=>{this.#cleanup()}))}[KEYMAP_EXTENSION_CONTEXT](){return{state:this.#state,host:this.#host,conditions:this.#conditions,catalog:this.#catalog,activation:this.#activation}}#cleanup(){if(this.#cleanedUp)return;this.#cleanedUp=!0,this.#activation.setPendingSequence(null);for(let resource of this.#resources.values())resource.dispose();this.#resources.clear(),this.#layers.cleanup();for(let cleanupListener of this.#cleanupListeners.splice(0))cleanupListener()}setData(name,value){this.#runtime.setData(name,value)}getData(name){return this.#runtime.getData(name)}getHostMetadata(){return this.#host.metadata}hasPendingSequence(){return this.#activation.ensureValidPendingSequence()!==void 0}createKeyMatcher(key){let match=this.#compiler.parseTokenKey(key).match;return(input)=>{if(!input)return!1;return getKeyMatchKey(input)===match}}parseKeySequence(key){return this.#compiler.parseKeySequence(key)}formatKey(key,options){return this.#compiler.formatKey(key,options)}clearPendingSequence(){this.#activation.setPendingSequence(null)}popPendingSequence(){return this.#activation.popPendingSequence()}getCommands(query2){return this.#catalog.getCommands(query2)}getCommandEntries(query2){return this.#catalog.getCommandEntries(query2)}getCommandBindings(query2){return this.#catalog.getCommandBindings(query2)}acquireResource(key,setup){if(this.#cleanedUp||this.#host.isDestroyed)throw Error("Cannot use a keymap after its host was destroyed");let existing=this.#resources.get(key);if(existing)return existing.count+=1,()=>{this.#releaseResource(key,existing)};let resource={count:1,dispose:setup()};return this.#resources.set(key,resource),()=>{this.#releaseResource(key,resource)}}runCommand(cmd,options){return this.#executor.runCommand(cmd,options)}dispatchCommand(cmd,options){return this.#executor.dispatchCommand(cmd,options)}on(name,fn){if(name==="warning")return this.#events.hook(name,fn);if(name==="error")return this.#events.hook(name,fn);return this.#hooks.hook(name,fn)}intercept(name,fn,options){if(name==="key")return this.#dispatch.intercept(name,fn,options);if(name==="key:after")return this.#dispatch.intercept(name,fn,options);return this.#dispatch.intercept(name,fn,options)}registerLayer(layer){return this.#layers.registerLayer(layer)}registerLayerFields(fields){return registerFields(this.#state,this.#notify,"layer",fields)}prependLayerBindingsTransformer(transformer){return this.#state.layerBindingsTransformers.prepend(transformer)}appendLayerBindingsTransformer(transformer){return this.#state.layerBindingsTransformers.append(transformer)}clearLayerBindingsTransformers(){this.#state.layerBindingsTransformers.clear()}prependBindingTransformer(transformer){return this.#state.bindingTransformers.prepend(transformer)}appendBindingTransformer(transformer){return this.#state.bindingTransformers.append(transformer)}clearBindingTransformers(){this.#state.bindingTransformers.clear()}prependCommandTransformer(transformer){return this.#state.commandTransformers.prepend(transformer)}appendCommandTransformer(transformer){return this.#state.commandTransformers.append(transformer)}clearCommandTransformers(){this.#state.commandTransformers.clear()}prependBindingParser(parser){return this.#state.bindingParsers.prepend(parser)}appendBindingParser(parser){return this.#state.bindingParsers.append(parser)}clearBindingParsers(){this.#state.bindingParsers.clear()}registerToken(token){return registerToken(this.#state,this.#notify,this.#compiler,this.#layers,token)}registerSequencePattern(pattern){return registerSequencePattern(this.#state,this.#notify,this.#layers,pattern)}prependBindingExpander(expander){return this.#state.bindingExpanders.prepend(expander)}appendBindingExpander(expander){return this.#state.bindingExpanders.append(expander)}clearBindingExpanders(){this.#state.bindingExpanders.clear()}registerBindingFields(fields){return registerFields(this.#state,this.#notify,"binding",fields)}registerCommandFields(fields){return registerFields(this.#state,this.#notify,"command",fields)}prependCommandResolver(resolver){return this.#catalog.prependCommandResolver(resolver)}appendCommandResolver(resolver){return this.#catalog.appendCommandResolver(resolver)}clearCommandResolvers(){this.#catalog.clearCommandResolvers()}prependLayerAnalyzer(analyzer){return this.#layerDiagnostics.prependLayerAnalyzer(analyzer)}appendLayerAnalyzer(analyzer){return this.#layerDiagnostics.appendLayerAnalyzer(analyzer)}clearLayerAnalyzers(){this.#layerDiagnostics.clearLayerAnalyzers()}prependEventMatchResolver(resolver){return this.#dispatch.prependEventMatchResolver(resolver)}appendEventMatchResolver(resolver){return this.#dispatch.appendEventMatchResolver(resolver)}clearEventMatchResolvers(){this.#dispatch.clearEventMatchResolvers()}prependDisambiguationResolver(resolver){return this.#dispatch.prependDisambiguationResolver(resolver)}appendDisambiguationResolver(resolver){return this.#dispatch.appendDisambiguationResolver(resolver)}clearDisambiguationResolvers(){this.#dispatch.clearDisambiguationResolvers()}#handleFocusedTargetChange(_focused){this.#notify.runWithStateChangeBatch(()=>{this.#activation.setPendingSequence(null),this.#notify.queueStateChange({invalidateCaches:!1})})}#warnUnknownField(kind,fieldName){this.#notify.warnOnce(`${kind}:${fieldName}`,`unknown-${kind}-field`,{field:fieldName,kind},`[Keymap] Unknown ${kind} field "${fieldName}" was ignored`)}#warnUnknownToken(token,sequence){this.#notify.warnOnce(`token:${token}`,"unknown-token",{token,sequence},`[Keymap] Unknown token "${token}" in key sequence "${sequence}" was ignored`)}#releaseResource(key,resource){if(this.#resources.get(key)!==resource)return;if(resource.count-=1,resource.count>0)return;resource.dispose(),this.#resources.delete(key)}}});function createPrefixBuckets(values2){let buckets=new Map;for(let value of values2){let first=value.charCodeAt(0);if(Number.isNaN(first))continue;let bucket=buckets.get(first);if(!bucket)bucket=[],buckets.set(first,bucket);bucket.push(value)}for(let bucket of buckets.values())bucket.sort((left,right)=>right.length-left.length);return buckets}function toLowerAsciiCode(code){return code>=65&&code<=90?code+32:code}function isDigitCode(code){return code>=48&&code<=57}function startsWithAsciiInsensitive(input,prefix,index){if(input.startsWith(prefix,index))return!0;if(index+prefix.length>input.length)return!1;for(let offset=0;offset<prefix.length;offset+=1)if(toLowerAsciiCode(input.charCodeAt(index+offset))!==prefix.charCodeAt(offset))return!1;return!0}function findBucketedPrefixMatch(buckets,input,index){let first=input.charCodeAt(index);if(Number.isNaN(first))return;let candidates=buckets.get(toLowerAsciiCode(first));if(!candidates)return;for(let candidate of candidates)if(startsWithAsciiInsensitive(input,candidate,index))return candidate;return}function parseObjectKeyInput(ctx,key,display,match,tokenName){return ctx.parseObjectKey(key,{display,match,tokenName})}function parseStringKeyPart(input,ctx){if(input===" ")return ctx.parseObjectKey({name:"space"},{display:"space"});if(input==="+")return ctx.parseObjectKey({name:"+"},{display:"+"});let parts=input.split("+"),name="",displayName="",ctrl=!1,shift=!1,meta=!1,superKey=!1,hyper=!1;for(let rawPart of parts){let part=rawPart.trim();if(!part)continue;let lowered=part.toLowerCase();if(lowered==="ctrl"||lowered==="control"){ctrl=!0;continue}if(lowered==="shift"){shift=!0;continue}if(lowered==="meta"||lowered==="alt"||lowered==="option"){meta=!0;continue}if(lowered==="super"){superKey=!0;continue}if(lowered==="hyper"){hyper=!0;continue}if(name)throw Error(`Invalid key "${input}": multiple key names are not supported`);name=part,displayName=lowered}if(!name)throw Error(`Invalid key "${input}": missing key name`);let displayParts=[];if(ctrl)displayParts.push("ctrl");if(shift)displayParts.push("shift");if(meta)displayParts.push("meta");if(superKey)displayParts.push("super");if(hyper)displayParts.push("hyper");return displayParts.push(displayName),ctx.parseObjectKey({name,ctrl,shift,meta,super:superKey,hyper:hyper||void 0},{display:displayParts.join("+")})}function parseNamedKeyPart(name,ctx){let normalized=name.trim().toLowerCase();return ctx.parseObjectKey({name:normalized},{display:normalized})}function findNamedSingleStrokeKey(input,index){let namedKey=findBucketedPrefixMatch(namedSingleStrokeKeyPrefixes,input,index);if(namedKey)return namedKey;if(toLowerAsciiCode(input.charCodeAt(index))!==102||!isDigitCode(input.charCodeAt(index+1)))return;let end=isDigitCode(input.charCodeAt(index+2))?index+3:index+2;return input.slice(index,end).toLowerCase()}function findModifierKey(input,index){return findBucketedPrefixMatch(modifierKeyPrefixes,input,index)}function parseModifiedKeyPart(input,index,ctx){let cursor=index,ctrl=!1,shift=!1,meta=!1,superKey=!1,hyper=!1;while(cursor<input.length){let modifier=findModifierKey(input,cursor);if(!modifier)break;let plusIndex=cursor+modifier.length;if(input[plusIndex]!=="+")break;if(modifier==="ctrl"||modifier==="control")ctrl=!0;else if(modifier==="shift")shift=!0;else if(modifier==="meta"||modifier==="alt"||modifier==="option")meta=!0;else if(modifier==="super")superKey=!0;else if(modifier==="hyper")hyper=!0;cursor=plusIndex+1}if(cursor===index)return;let char=input[cursor];if(char===void 0)throw Error(`Invalid key "${input.slice(index)}": missing key name`);let name=findNamedSingleStrokeKey(input,cursor)??char,displayName=name===" "?"space":name==="+"?"+":name.toLowerCase(),displayParts=[];if(ctrl)displayParts.push("ctrl");if(shift)displayParts.push("shift");if(meta)displayParts.push("meta");if(superKey)displayParts.push("super");if(hyper)displayParts.push("hyper");return displayParts.push(displayName),{part:ctx.parseObjectKey({name:name===" "?"space":name,ctrl,shift,meta,super:superKey,hyper:hyper||void 0},{display:displayParts.join("+")}),nextIndex:cursor+name.length}}function registerDefaultBindingParser(keymap){return keymap.appendBindingParser((ctx)=>defaultBindingParser(ctx))}function registerDefaultEventMatchResolver(keymap){return keymap.appendEventMatchResolver((event,ctx)=>defaultEventMatchResolver(event,ctx))}function registerDefaultKeys(keymap){let offParser=registerDefaultBindingParser(keymap),offResolver=registerDefaultEventMatchResolver(keymap);return()=>{offResolver(),offParser()}}function registerEscapeClearsPendingSequence(keymap,options){let shouldPreventDefault=options?.preventDefault??!0;return keymap.intercept("key",({event,consume})=>{if(event.name!=="escape")return;if(!keymap.hasPendingSequence())return;if(keymap.clearPendingSequence(),shouldPreventDefault)consume()},{priority:options?.priority??0})}function isReactiveMatcher2(value){if(!value||typeof value!=="object")return!1;let candidate=value;return typeof candidate.get==="function"&&typeof candidate.subscribe==="function"}function normalizeEnabledValue(fieldName,value){if(typeof value==="boolean")return value;if(typeof value==="function")return value;if(isReactiveMatcher2(value))return value;throw Error(`Keymap enabled field "${fieldName}" must be a boolean, a function, or a reactive matcher`)}function registerEnabledFields(keymap){return keymap.acquireResource(ENABLED_FIELDS_RESOURCE,()=>{let offLayerFields=keymap.registerLayerFields({enabled(value,ctx){let normalized=normalizeEnabledValue("enabled",value);if(normalized===!0)return;if(normalized===!1){ctx.activeWhen(()=>!1);return}ctx.activeWhen(normalized)}}),offCommandFields=keymap.registerCommandFields({enabled(value,ctx){let normalized=normalizeEnabledValue("enabled",value);if(normalized===!0)return;if(normalized===!1){ctx.activeWhen(()=>!1);return}ctx.activeWhen(normalized)}});return()=>{offCommandFields(),offLayerFields()}})}function isLeaderTriggerArray(trigger){return Array.isArray(trigger)}function resolveLeaderTrigger(trigger){if(isLeaderTriggerArray(trigger)){if(trigger.length!==1)throw Error("Invalid leader trigger: expected exactly one binding");return trigger[0].key}if(typeof trigger==="object"&&"key"in trigger)return trigger.key;return trigger}function registerLeader(keymap,options){return keymap.registerToken({name:options.name??"leader",key:resolveLeaderTrigger(options.trigger)})}function normalizeMetadataText(fieldName,value){if(typeof value!=="string")throw Error(`Keymap metadata field "${fieldName}" must be a string`);let trimmed=value.trim();if(!trimmed)throw Error(`Keymap metadata field "${fieldName}" cannot be empty`);return trimmed}function registerMetadataFields(keymap){return keymap.acquireResource(METADATA_FIELDS_RESOURCE,()=>{let offBindingFields=keymap.registerBindingFields({desc(value,ctx){ctx.attr("desc",normalizeMetadataText("desc",value))},group(value,ctx){ctx.attr("group",normalizeMetadataText("group",value))}}),offCommandFields=keymap.registerCommandFields({desc(value,ctx){ctx.attr("desc",normalizeMetadataText("desc",value))},title(value,ctx){ctx.attr("title",normalizeMetadataText("title",value))},category(value,ctx){ctx.attr("category",normalizeMetadataText("category",value))}});return()=>{offCommandFields(),offBindingFields()}})}var namedSingleStrokeKeys,modifierKeyNames,namedSingleStrokeKeyPrefixes,modifierKeyPrefixes,defaultBindingParser=(ctx)=>{let{input,index,tokens:tokens2,normalizeTokenName}=ctx;if(index===0&&input.includes("+")&&/\s/.test(input))return{parts:[parseStringKeyPart(input,ctx)],nextIndex:input.length};let char=input[index];if(char===void 0)return;if(char==="<"){let end=input.indexOf(">",index);if(end===-1)return{parts:[parseStringKeyPart(char,ctx)],nextIndex:index+1};let tokenName=normalizeTokenName(input.slice(index+1,end)),token=tokens2.get(tokenName);if(!token)return{parts:[],nextIndex:end+1,unknownTokens:[tokenName]};return{parts:[parseObjectKeyInput(ctx,token.stroke,`<${tokenName}>`,token.match,tokenName)],nextIndex:end+1,usedTokens:[tokenName]}}if(char==="{"){let end=input.indexOf("}",index);if(end===-1)return{parts:[parseStringKeyPart(char,ctx)],nextIndex:index+1};let patternName=normalizeTokenName(input.slice(index+1,end)),pattern=ctx.patterns.get(patternName);if(!pattern)return{parts:[],nextIndex:end+1,unknownTokens:[patternName]};return{parts:[{...ctx.parseObjectKey({name:patternName,ctrl:!1,shift:!1,meta:!1,super:!1},{display:pattern.display??`{${patternName}}`,match:pattern.match}),patternName:pattern.name,payloadKey:pattern.payloadKey}],nextIndex:end+1,usedTokens:[patternName]}}let modified=parseModifiedKeyPart(input,index,ctx);if(modified)return{parts:[modified.part],nextIndex:modified.nextIndex};let namedKey=findNamedSingleStrokeKey(input,index);if(namedKey)return{parts:[parseNamedKeyPart(namedKey,ctx)],nextIndex:index+namedKey.length};return{parts:[parseStringKeyPart(char,ctx)],nextIndex:index+1}},defaultEventMatchResolver=(event,ctx)=>{return[ctx.resolveKey({name:event.name,ctrl:event.ctrl,shift:event.shift,meta:event.meta,super:event.super??!1,hyper:event.hyper||void 0})]},BINDING_OVERRIDES_RESOURCE,ALIASES_FIELD_RESOURCE,COMMA_BINDINGS_RESOURCE,DEAD_BINDING_WARNINGS_RESOURCE,ENABLED_FIELDS_RESOURCE,EMACS_BINDINGS_RESOURCE,EX_COMMANDS_RESOURCE,METADATA_FIELDS_RESOURCE,MOD_BINDINGS_RESOURCE,UNRESOLVED_COMMAND_WARNINGS_RESOURCE;var init_addons=__esm(()=>{init_src2();init_src2();namedSingleStrokeKeys=new Set(["up","down","left","right","clear","escape","return","linefeed","enter","tab","backspace","delete","insert","home","end","pageup","pagedown","space","lt","gt","plus","minus","equal","comma","period","slash","backslash","semicolon","quote","backquote","leftbracket","rightbracket","capslock","numlock","scrolllock","printscreen","pause","menu","apps","kp0","kp1","kp2","kp3","kp4","kp5","kp6","kp7","kp8","kp9","kpdecimal","kpdivide","kpmultiply","kpminus","kpplus","kpenter","kpequal","kpseparator","kpleft","kpright","kpup","kpdown","kppageup","kppagedown","kphome","kpend","kpinsert","kpdelete","mediaplay","mediapause","mediaplaypause","mediareverse","mediastop","mediafastforward","mediarewind","medianext","mediaprev","mediarecord","volumedown","volumeup","mute","leftshift","leftctrl","leftalt","leftsuper","lefthyper","leftmeta","rightshift","rightctrl","rightalt","rightsuper","righthyper","rightmeta","iso_level3_shift","iso_level5_shift","option","alt","meta","super","hyper","control","ctrl","shift"]),modifierKeyNames=new Set(["ctrl","control","shift","meta","alt","option","super","hyper"]),namedSingleStrokeKeyPrefixes=createPrefixBuckets(namedSingleStrokeKeys),modifierKeyPrefixes=createPrefixBuckets(modifierKeyNames);BINDING_OVERRIDES_RESOURCE=Symbol("keymap:binding-overrides"),ALIASES_FIELD_RESOURCE=Symbol("keymap:aliases-field"),COMMA_BINDINGS_RESOURCE=Symbol("keymap:comma-bindings"),DEAD_BINDING_WARNINGS_RESOURCE=Symbol("keymap:dead-binding-warnings");ENABLED_FIELDS_RESOURCE=Symbol("keymap:enabled-fields");EMACS_BINDINGS_RESOURCE=Symbol("keymap:emacs-bindings"),EX_COMMANDS_RESOURCE=Symbol("keymap:ex-commands");METADATA_FIELDS_RESOURCE=Symbol("keymap:metadata-fields");MOD_BINDINGS_RESOURCE=Symbol("keymap:mod-bindings"),UNRESOLVED_COMMAND_WARNINGS_RESOURCE=Symbol("keymap:unresolved-command-warnings")});function createSyntheticCommandEvent(){return new KeyEvent({name:"command",ctrl:!1,meta:!1,shift:!1,option:!1,sequence:"",number:!1,raw:"",eventType:"press",source:"raw"})}function normalizeRuntimePlatform(platform2){if(platform2==="darwin")return"macos";if(platform2==="win32")return"windows";if(platform2==="linux")return"linux";return"unknown"}function createOpenTuiHostMetadata(renderer){let platform2=normalizeRuntimePlatform(process.platform),hasKittyKeyboard=renderer.capabilities?.kitty_keyboard===!0;return{platform:platform2,primaryModifier:platform2==="macos"?"super":platform2==="unknown"?"unknown":"ctrl",modifiers:{ctrl:"supported",shift:"supported",meta:"supported",super:hasKittyKeyboard?"supported":"unknown",hyper:hasKittyKeyboard?"supported":"unknown"}}}function createOpenTuiKeymapHost(renderer){return{get metadata(){return createOpenTuiHostMetadata(renderer)},rootTarget:renderer.root,get isDestroyed(){return renderer.isDestroyed},getFocusedTarget(){let focused=renderer.currentFocusedRenderable;if(!focused||focused.isDestroyed||!focused.focused)return null;return focused},getParentTarget(target){return target.parent},isTargetDestroyed(target){return target.isDestroyed},onKeyPress(listener){return renderer.keyInput.prependListener("keypress",listener),()=>{renderer.keyInput.off("keypress",listener)}},onKeyRelease(listener){return renderer.keyInput.prependListener("keyrelease",listener),()=>{renderer.keyInput.off("keyrelease",listener)}},onFocusChange(listener){return renderer.on(CliRenderEvents.FOCUSED_RENDERABLE,listener),()=>{renderer.off(CliRenderEvents.FOCUSED_RENDERABLE,listener)}},onDestroy(listener){return renderer.once(CliRenderEvents.DESTROY,listener),()=>{renderer.off(CliRenderEvents.DESTROY,listener)}},onTargetDestroy(target,listener){return target.once(RenderableEvents.DESTROYED,listener),()=>{target.off(RenderableEvents.DESTROYED,listener)}},onRawInput(listener){return renderer.prependInputHandler(listener),()=>{renderer.removeInputHandler(listener)}},createCommandEvent(){return createSyntheticCommandEvent()}}}function createDefaultOpenTuiKeymap(renderer){if(renderer.isDestroyed)throw Error("Cannot create a keymap for a destroyed renderer");let keymap=new Keymap(createOpenTuiKeymapHost(renderer));return registerDefaultKeys(keymap),registerEnabledFields(keymap),registerMetadataFields(keymap),keymap}var init_opentui=__esm(async()=>{init_src2();init_addons();await init_core()});function createTuiKeymap(renderer){let keymap=createDefaultOpenTuiKeymap(renderer);return registerLeader(keymap,{trigger:{name:"space"}}),registerEscapeClearsPendingSequence(keymap),keymap}var init_keymap=__esm(async()=>{init_addons();await init_opentui()});import{spawnSync as spawnSync10}from"child_process";import{existsSync as existsSync77}from"fs";function resolveTuiTmuxConf(){let tuiConf=`${process.env.GENIE_HOME??`${process.env.HOME}/.genie`}/tui-tmux.conf`;return existsSync77(tuiConf)?tuiConf:"/dev/null"}function safeHex(value,fallback){if(!value)return fallback;let trimmed=value.trim();return HEX_COLOR_RE.test(trimmed)?trimmed:fallback}function resolveThemePalette(snapshot){if(snapshot.mode==="dark")return{bg:palette.bg,bgRaised:palette.bgRaised,text:palette.text,textDim:palette.textDim,textMuted:palette.textMuted,border:palette.border,accent:palette.accent,accentDim:palette.accentDim,accentBright:palette.accentBright,warning:palette.warning,info:palette.info};return{...lightPalette,bg:safeHex(snapshot.terminalBackground,lightPalette.bg),text:safeHex(snapshot.terminalForeground,lightPalette.text)}}function flattenTmuxCommands(commands){let args=[];return commands.forEach((command,index)=>{if(index>0)args.push(";");args.push(...command)}),args}function buildTuiTmuxThemeCommands(snapshot){let theme=resolveThemePalette(snapshot),terminalForeground=safeHex(snapshot.terminalForeground,theme.text),terminalBackground=safeHex(snapshot.terminalBackground,theme.bg);return flattenTmuxCommands([["set-environment","-g","GENIE_TUI_THEME_MODE",snapshot.mode],["set-environment","-g","GENIE_TUI_TERMINAL_FG",terminalForeground],["set-environment","-g","GENIE_TUI_TERMINAL_BG",terminalBackground],["set-environment","-g","GENIE_TUI_TMUX_BG",theme.bg],["set-environment","-g","GENIE_TUI_TMUX_TEXT",theme.text],["set-environment","-g","GENIE_TUI_TMUX_ACCENT",theme.accent],["set-option","-g","pane-border-style",`fg=${theme.border}`],["set-option","-g","pane-active-border-style",`fg=${theme.accent}`],["set-option","-g","message-style",`bg=${theme.bgRaised},fg=${theme.info}`],["set-option","-g","message-command-style",`bg=${theme.bgRaised},fg=${theme.warning}`],["set-option","-g","status-style",`bg=${theme.bg},fg=${theme.text}`],["set-window-option","-g","mode-style",`bg=${theme.accent},fg=${theme.bg}`],["set-window-option","-g","clock-mode-colour",theme.accent]])}function syncTuiTmuxTheme(snapshot,deps={}){let run=deps.spawnSync??spawnSync10,tmux=deps.tmuxBin??tmuxBin(),socketName=deps.socketName??TUI_TMUX_SOCKET,configPath2=deps.configPath??resolveTuiTmuxConf(),timeoutMs=deps.timeoutMs??DEFAULT_TMUX_SYNC_TIMEOUT_MS;return run(tmux,["-L",socketName,"-f",configPath2,...buildTuiTmuxThemeCommands(snapshot)],{stdio:"ignore",timeout:timeoutMs}).status===0}var TUI_TMUX_SOCKET="genie-tui",DEFAULT_TMUX_SYNC_TIMEOUT_MS=300,HEX_COLOR_RE,lightPalette;var init_tmux_theme_sync=__esm(()=>{init_ensure_tmux();init_theme2();HEX_COLOR_RE=/^#[0-9a-f]{6}$/i,lightPalette={bg:"#f5efe4",bgRaised:"#ebe3d7",text:"#24323a",textDim:"#56656d",textMuted:"#718087",border:"#c8bdae",accent:"#2f7a62",accentDim:"#3e9277",accentBright:"#17694f",warning:"#9a651e",info:"#406f8b"}});function readBool(env2,name,fallback){let raw=env2[name];if(!raw)return fallback;let normalized=raw.trim().toLowerCase();if(TRUTHY3.has(normalized))return!0;if(FALSY.has(normalized))return!1;return fallback}function readPositiveInt(env2,name,fallback){let raw=env2[name];if(!raw)return fallback;let parsed=Number.parseInt(raw,10);return Number.isFinite(parsed)&&parsed>0?parsed:fallback}function inferThemeMode(background){if(!background||!/^#[0-9a-f]{6}$/i.test(background))return null;let r=Number.parseInt(background.slice(1,3),16),g2=Number.parseInt(background.slice(3,5),16),b3=Number.parseInt(background.slice(5,7),16);return(0.2126*r+0.7152*g2+0.0722*b3)/255>=0.5?"light":"dark"}function snapshotKey(snapshot){return[snapshot.mode,snapshot.terminalForeground??"",snapshot.terminalBackground??""].join("|")}function buildSnapshot(mode,colors8){let resolvedMode=mode??inferThemeMode(colors8?.defaultBackground);if(!resolvedMode)return null;return{mode:resolvedMode,terminalForeground:colors8?.defaultForeground,terminalBackground:colors8?.defaultBackground}}function installOpenTui20Bridge(renderer,options={}){let env2=options.env??process.env;if(!readBool(env2,"GENIE_TUI_TMUX_THEME_SYNC",!0))return()=>{};let syncTheme=options.syncTheme??syncTuiTmuxTheme,themeQueryTimeoutMs=readPositiveInt(env2,"GENIE_TUI_THEME_QUERY_TIMEOUT_MS",DEFAULT_THEME_QUERY_TIMEOUT_MS),tmuxApplyTimeoutMs=readPositiveInt(env2,"GENIE_TUI_TMUX_THEME_SYNC_TIMEOUT_MS",DEFAULT_TMUX_APPLY_TIMEOUT_MS),disposed=!1,lastSnapshot="",syncSnapshot=(snapshot)=>{if(disposed||!snapshot)return;let key=snapshotKey(snapshot);if(key===lastSnapshot)return;lastSnapshot=key;try{syncTheme(snapshot,{timeoutMs:tmuxApplyTimeoutMs})}catch{}},syncFromMode=(mode,colors8)=>{syncSnapshot(buildSnapshot(mode,colors8))},onThemeMode=(mode)=>syncFromMode(mode);renderer.on("theme_mode",onThemeMode),syncFromMode(renderer.themeMode),renderer.waitForThemeMode(themeQueryTimeoutMs).then((mode)=>syncFromMode(mode)).catch(()=>{});let paletteOptions={size:OPEN_TUI_02_PALETTE_SIZE,timeout:themeQueryTimeoutMs};return renderer.getPalette(paletteOptions).then((colors8)=>syncFromMode(renderer.themeMode,colors8)).catch(()=>{}),()=>{disposed=!0,renderer.off("theme_mode",onThemeMode)}}var TRUTHY3,FALSY,DEFAULT_THEME_QUERY_TIMEOUT_MS=700,DEFAULT_TMUX_APPLY_TIMEOUT_MS=300,OPEN_TUI_02_PALETTE_SIZE=16;var init_opentui_bridge=__esm(()=>{init_tmux_theme_sync();TRUTHY3=new Set(["1","true","yes","on"]),FALSY=new Set(["0","false","no","off"])});var exports_render={};__export(exports_render,{resolveTuiRendererConfig:()=>resolveTuiRendererConfig,renderNav:()=>renderNav,installNativeSelectionOverride:()=>installNativeSelectionOverride,disableDragTracking:()=>disableDragTracking});function disableDragTracking(stdout=process.stdout){stdout.write(ESC_DISABLE_DRAG_TRACKING)}function installNativeSelectionOverride(renderer,stdout=process.stdout){let originalEnableMouse=renderer.enableMouse.bind(renderer);renderer.enableMouse=()=>{originalEnableMouse(),disableDragTracking(stdout)},disableDragTracking(stdout)}function readBool2(env2,name,fallback){let raw=env2[name];if(!raw)return fallback;let normalized=raw.trim().toLowerCase();if(TRUTHY4.has(normalized))return!0;if(FALSY2.has(normalized))return!1;return fallback}function readPositiveInt2(env2,name){let raw=env2[name];if(!raw)return;let parsed=Number.parseInt(raw,10);return Number.isFinite(parsed)&&parsed>0?parsed:void 0}function resolveTuiRendererConfig(env2=process.env,platform2=process.platform){let isDarwin=platform2==="darwin",targetFps=readPositiveInt2(env2,"GENIE_TUI_TARGET_FPS")??(isDarwin?8:30),configuredMaxFps=readPositiveInt2(env2,"GENIE_TUI_MAX_FPS")??(isDarwin?12:60),maxFps=Math.max(configuredMaxFps,targetFps),useMouse=readBool2(env2,"GENIE_TUI_MOUSE",!0),enableMouseMovement=useMouse&&readBool2(env2,"GENIE_TUI_MOUSE_MOVEMENT",!isDarwin),consoleEnabled=readBool2(env2,"GENIE_TUI_CONSOLE",!0),kittyKeyboardOptIn=readBool2(env2,"GENIE_TUI_KITTY_KEYBOARD",!isDarwin);return{exitOnCtrlC:!1,useThread:!isDarwin,targetFps,maxFps,useMouse,enableMouseMovement,useKittyKeyboard:kittyKeyboardOptIn?void 0:null,consoleMode:consoleEnabled?void 0:"disabled",openConsoleOnError:consoleEnabled&&!isDarwin}}async function renderNav(){let rightPane=process.env.GENIE_TUI_RIGHT||void 0,workspaceRoot=process.env.GENIE_TUI_WORKSPACE||void 0,initialAgent=process.env.GENIE_TUI_AGENT||void 0,renderer=await createCliRenderer(resolveTuiRendererConfig());installNativeSelectionOverride(renderer);let disposeOpenTui20Bridge=installOpenTui20Bridge(renderer),keymap=createTuiKeymap(renderer);createRoot(renderer).render(import_jsx_dev_runtime2.jsxDEV(KeymapProvider,{keymap,children:import_jsx_dev_runtime2.jsxDEV(App,{rightPane,workspaceRoot,initialAgent},void 0,!1,void 0,this)},void 0,!1,void 0,this)),await new Promise((resolve23)=>{renderer.once("destroy",()=>{disposeOpenTui20Bridge(),resolve23()})})}var ESC_DISABLE_DRAG_TRACKING="\x1B[?1002l",TRUTHY4,FALSY2;var init_render=__esm(async()=>{init_react();init_opentui_bridge();init_jsx_dev_runtime();await __promiseAll([init_core(),init_react2(),init_app(),init_keymap()]);TRUTHY4=new Set(["1","true","yes","on"]),FALSY2=new Set(["0","false","no","off"])});var exports_tui={};__export(exports_tui,{launchTui:()=>launchTui});import{appendFileSync as appendFileSync6,closeSync as closeSync6,mkdirSync as mkdirSync35,openSync as openSync6,readSync as readSync3,statSync as statSync17}from"fs";import{homedir as homedir52}from"os";import{join as join94}from"path";function genieHome6(){return process.env.GENIE_HOME??join94(homedir52(),".genie")}function extractPreviousRunCrashOutput(logPath){let fd=null;try{let size=statSync17(logPath).size;if(size===0)return"";let readSize=Math.min(size,TUI_CRASH_LOG_RECOVERY_MAX_BYTES);fd=openSync6(logPath,"r");let buffer2=Buffer.alloc(readSize);readSync3(fd,buffer2,0,readSize,size-readSize);let text=buffer2.toString("utf-8"),lastBannerIndex=text.lastIndexOf(TUI_CRASH_LOG_BANNER_PREFIX);if(lastBannerIndex<0)return"";let afterBannerNewline=text.indexOf(`
4019
4019
  `,lastBannerIndex);if(afterBannerNewline<0)return"";return text.slice(afterBannerNewline+1).trim()}catch{return""}finally{if(fd!==null)try{closeSync6(fd)}catch{}}}async function ingestPreviousRunCrash(logPath){let body=extractPreviousRunCrashOutput(logPath);if(!body)return;let truncated=body.length>TUI_CRASH_LOG_RECOVERY_MAX_MSG_CHARS?`${body.slice(0,TUI_CRASH_LOG_RECOVERY_MAX_MSG_CHARS)}
4020
4020
  \u2026[truncated]`:body;try{let{emitEvent:emitEvent2}=await Promise.resolve().then(() => (init_emit(),exports_emit));emitEvent2("error.raised",{error_class:"TuiCrash",message:truncated,subsystem:"tui",severity:"error",retryable:!0})}catch{}}async function recordTuiLaunchBreadcrumb(){try{let logsDir=join94(genieHome6(),"logs");mkdirSync35(logsDir,{recursive:!0});let logPath=join94(logsDir,"tui-crash.log");await ingestPreviousRunCrash(logPath);let ts3=new Date().toISOString(),line=`${TUI_CRASH_LOG_BANNER_PREFIX}${ts3} pid=${process.pid} platform=${process.platform} arch=${process.arch} ---
4021
- `;appendFileSync6(logPath,line,{mode:420})}catch{}}function installTuiExitSignals(){let exitOnSignal=(signal)=>{process.exit(signal==="SIGHUP"?0:128+(signal==="SIGINT"?2:15))};process.on("SIGHUP",exitOnSignal),process.on("SIGINT",exitOnSignal),process.on("SIGTERM",exitOnSignal)}async function launchTui(){installTuiExitSignals(),await recordTuiLaunchBreadcrumb();let{renderNav:renderNav2}=await init_render().then(() => exports_render);await renderNav2()}var TUI_CRASH_LOG_BANNER_PREFIX="--- tui-launch ",TUI_CRASH_LOG_RECOVERY_MAX_BYTES=65536,TUI_CRASH_LOG_RECOVERY_MAX_MSG_CHARS=3000;var init_tui=()=>{};var exports_resolve_agent_cwd={};__export(exports_resolve_agent_cwd,{resolveAgentFromCwd:()=>resolveAgentFromCwd});import{existsSync as existsSync78}from"fs";import{basename as basename16,dirname as dirname35,join as join95,relative as relative10,sep as sep3}from"path";function isRelativeWithin(rel,original){return!rel.startsWith("..")&&rel!==original}function resolveFromCanonicalDir(cwd,agentsDir){let relToAgents=relative10(agentsDir,cwd);if(!isRelativeWithin(relToAgents,cwd))return null;let segments=relToAgents.split(sep3).filter(Boolean);if(segments.length===0)return null;let agentName=segments[0];if(!existsSync78(join95(agentsDir,agentName,"AGENTS.md")))return null;let source=segments.length===1?"exact":"parent";return{agent:agentName,source}}function resolveFromWalkUp(cwd,workspaceRoot){let wsRel=relative10(workspaceRoot,cwd);if(!isRelativeWithin(wsRel,cwd))return null;let current=cwd;while(current!==workspaceRoot&&current!==dirname35(current)){if(existsSync78(join95(current,"AGENTS.md")))return{agent:basename16(current),source:"parent"};current=dirname35(current)}return null}function resolveAgentFromCwd(cwd,workspaceRoot){return resolveFromCanonicalDir(cwd,join95(workspaceRoot,"agents"))??resolveFromWalkUp(cwd,workspaceRoot)??{agent:"genie",source:"default"}}var init_resolve_agent_cwd=()=>{};var import__=__toESM(require_commander(),1),{program,createCommand,createArgument,createOption,CommanderError,InvalidArgumentError,InvalidOptionArgumentError,Command,Argument,Option,Help}=import__.default;init_doctor();import{execFileSync as execFileSync2,spawnSync as spawnSync2}from"child_process";import{existsSync as existsSync21,mkdirSync as mkdirSync11,readFileSync as readFileSync14,writeFileSync as writeFileSync8}from"fs";import{homedir as homedir21}from"os";import{dirname as dirname9,join as join26,resolve as resolve4}from"path";var PM2_PROCESS_NAME="Genie",PM2_LOG_PREFIX="genie-serve",LEGACY_PM2_PROCESS_NAMES=["genie-serve"],HARDENED_DEFAULTS={maxRestarts:50,minUptimeMs:1e4,restartDelayMs:4000,expBackoffRestartDelayMs:100,maxMemory:process.env.GENIE_SERVE_MAX_MEMORY||"4G",killTimeoutMs:60000,logDateFormat:"YYYY-MM-DD HH:mm:ss.SSS"};function getLogsDir(){return join26(homedir21(),".genie","logs")}function ok(msg){process.stdout.write(`genie install: ${msg}
4021
+ `;appendFileSync6(logPath,line,{mode:420})}catch{}}function installTuiExitSignals(){let exitOnSignal=(signal)=>{process.exit(signal==="SIGHUP"?0:128+(signal==="SIGINT"?2:15))};process.on("SIGHUP",exitOnSignal),process.on("SIGINT",exitOnSignal),process.on("SIGTERM",exitOnSignal)}async function launchTui(){installTuiExitSignals(),await recordTuiLaunchBreadcrumb();let{renderNav:renderNav2}=await init_render().then(() => exports_render);await renderNav2()}var TUI_CRASH_LOG_BANNER_PREFIX="--- tui-launch ",TUI_CRASH_LOG_RECOVERY_MAX_BYTES=65536,TUI_CRASH_LOG_RECOVERY_MAX_MSG_CHARS=3000;var init_tui=()=>{};var exports_resolve_agent_cwd={};__export(exports_resolve_agent_cwd,{resolveAgentFromCwd:()=>resolveAgentFromCwd});import{existsSync as existsSync78}from"fs";import{basename as basename16,dirname as dirname36,join as join95,relative as relative10,sep as sep3}from"path";function isRelativeWithin(rel,original){return!rel.startsWith("..")&&rel!==original}function resolveFromCanonicalDir(cwd,agentsDir){let relToAgents=relative10(agentsDir,cwd);if(!isRelativeWithin(relToAgents,cwd))return null;let segments=relToAgents.split(sep3).filter(Boolean);if(segments.length===0)return null;let agentName=segments[0];if(!existsSync78(join95(agentsDir,agentName,"AGENTS.md")))return null;let source=segments.length===1?"exact":"parent";return{agent:agentName,source}}function resolveFromWalkUp(cwd,workspaceRoot){let wsRel=relative10(workspaceRoot,cwd);if(!isRelativeWithin(wsRel,cwd))return null;let current=cwd;while(current!==workspaceRoot&&current!==dirname36(current)){if(existsSync78(join95(current,"AGENTS.md")))return{agent:basename16(current),source:"parent"};current=dirname36(current)}return null}function resolveAgentFromCwd(cwd,workspaceRoot){return resolveFromCanonicalDir(cwd,join95(workspaceRoot,"agents"))??resolveFromWalkUp(cwd,workspaceRoot)??{agent:"genie",source:"default"}}var init_resolve_agent_cwd=()=>{};var import__=__toESM(require_commander(),1),{program,createCommand,createArgument,createOption,CommanderError,InvalidArgumentError,InvalidOptionArgumentError,Command,Argument,Option,Help}=import__.default;init_doctor();import{execFileSync as execFileSync2,spawnSync as spawnSync2}from"child_process";import{existsSync as existsSync21,mkdirSync as mkdirSync11,readFileSync as readFileSync14,writeFileSync as writeFileSync8}from"fs";import{homedir as homedir21}from"os";import{dirname as dirname9,join as join26,resolve as resolve4}from"path";var PM2_PROCESS_NAME="Genie",PM2_LOG_PREFIX="genie-serve",LEGACY_PM2_PROCESS_NAMES=["genie-serve"],HARDENED_DEFAULTS={maxRestarts:50,minUptimeMs:1e4,restartDelayMs:4000,expBackoffRestartDelayMs:100,maxMemory:process.env.GENIE_SERVE_MAX_MEMORY||"4G",killTimeoutMs:60000,logDateFormat:"YYYY-MM-DD HH:mm:ss.SSS"};function getLogsDir(){return join26(homedir21(),".genie","logs")}function ok(msg){process.stdout.write(`genie install: ${msg}
4022
4022
  `)}function fail(msg){process.stderr.write(`genie install: ${msg}
4023
4023
  `),process.exit(1)}function which(cmd){try{return execFileSync2("which",[cmd],{encoding:"utf8",timeout:3000,stdio:["ignore","pipe","ignore"]}).trim()||null}catch{return null}}function pm2GetProcess(name){try{let out=execFileSync2("pm2",["jlist"],{encoding:"utf8",timeout:5000,stdio:["ignore","pipe","ignore"]});return JSON.parse(out).find((p)=>p.name===name)??null}catch{return null}}function removeLegacyPm2Entries(log=()=>{}){let removed=[];for(let legacyName of LEGACY_PM2_PROCESS_NAMES){if(!pm2GetProcess(legacyName))continue;try{execFileSync2("pm2",["delete",legacyName],{encoding:"utf8",timeout:1e4,stdio:["ignore","pipe","pipe"]}),log(`removed legacy pm2 entry "${legacyName}" (renamed to "${PM2_PROCESS_NAME}")`),removed.push(legacyName)}catch(err){let reason=err instanceof Error?err.message:String(err);log(`legacy pm2 entry "${legacyName}" present but pm2 delete failed: ${reason}`),log(` manual cleanup: pm2 delete ${legacyName}`)}}return removed}function pm2IsAvailable(){try{return execFileSync2("pm2",["--version"],{encoding:"utf8",timeout:3000,stdio:["ignore","pipe","ignore"]}),!0}catch{return!1}}function pgserveIsAvailable(){return which("pgserve")!==null}function buildCanonicalPgserveHint(reason){return[`Error: canonical pgserve registration failed (${reason}).`,"Genie depends on pm2-supervised pgserve. To proceed:"," bun add -g pgserve@^2"," pgserve install"," genie install","See https://github.com/automagik-dev/genie/blob/main/docs/install.md for details.",""].join(`
4024
4024
  `)}function failCanonicalPgserve(reason){process.stderr.write(buildCanonicalPgserveHint(reason)),process.exit(1)}function requirePgserveInstall(){if(!pgserveIsAvailable())failCanonicalPgserve("pgserve binary not found in PATH");let result2=spawnSync2("pgserve",["install"],{stdio:"inherit"});if(result2.status!==0)failCanonicalPgserve(`exit code ${result2.status}`)}function tryPgservePort(){if(!pgserveIsAvailable())return null;let result2=spawnSync2("pgserve",["port"],{encoding:"utf8",timeout:5000});if(result2.status!==0)return null;let port=Number.parseInt((result2.stdout??"").trim(),10);if(!Number.isFinite(port)||port<=0||port>65535)return null;return port}function buildGenieDatabaseUrl(port){return`postgresql://postgres:postgres@localhost:${port}/genie`}function resolveGenieBinary(){let wired=which("genie");if(wired)return wired;return process.argv[1]??"genie"}var MAX_PACKAGE_JSON_WALK_DEPTH=10;function readGenieVersionFromDisk(geniePath){let current=dirname9(resolve4(geniePath));for(let depth=0;depth<MAX_PACKAGE_JSON_WALK_DEPTH;depth++){let candidate=join26(current,"package.json");if(existsSync21(candidate))try{let pkg=JSON.parse(readFileSync14(candidate,"utf-8"));if(pkg.name==="@automagik/genie"&&typeof pkg.version==="string"&&pkg.version.length>0)return pkg.version}catch{}let parent=dirname9(current);if(parent===current)break;current=parent}return null}function getEcosystemConfigPath(){return join26(homedir21(),".genie",`${PM2_PROCESS_NAME}.config.cjs`)}function buildEcosystemConfigSource(geniePath,databaseUrl){let logs={out:join26(getLogsDir(),`${PM2_LOG_PREFIX}-out.log`),error:join26(getLogsDir(),`${PM2_LOG_PREFIX}-error.log`)},version=readGenieVersionFromDisk(geniePath),cfg={name:PM2_PROCESS_NAME,script:geniePath,args:"serve start --headless --no-tui --no-interactive",interpreter:"none",autorestart:!0,max_restarts:HARDENED_DEFAULTS.maxRestarts,min_uptime:HARDENED_DEFAULTS.minUptimeMs,restart_delay:HARDENED_DEFAULTS.restartDelayMs,exp_backoff_restart_delay:HARDENED_DEFAULTS.expBackoffRestartDelayMs,max_memory_restart:HARDENED_DEFAULTS.maxMemory,kill_timeout:HARDENED_DEFAULTS.killTimeoutMs,log_date_format:HARDENED_DEFAULTS.logDateFormat,error_file:logs.error,out_file:logs.out,merge_logs:!0,time:!0};if(version)cfg.version=version;if(databaseUrl)cfg.env={DATABASE_URL:databaseUrl};return`// Generated by \`genie install\` and \`genie update\` \u2014 do not edit by hand.
@@ -4049,11 +4049,14 @@ module.exports = {
4049
4049
  SELECT current_executor_id FROM agents WHERE id = ${agentRow.id} LIMIT 1
4050
4050
  `;agentRow.current_executor_id=rows[0]?.current_executor_id??null;let outcome=await attachOrphan({agentRow,agentLive:!1,candidate:newest});outcomes.push(outcome)}catch(err){skipped.push({reason:err instanceof Error?err.message:String(err),sessionId:newest.sessionId})}}return{outcomes,skipped}}async function applyUuid(summaries,uuid){for(let s of summaries){let candidate=s.orphans.find((o)=>o.sessionId===uuid);if(!candidate)continue;if(!s.agent)return{outcomes:[],skipped:[{reason:"no agent claims this cwd",sessionId:uuid}]};if(s.agentHasLiveExecutor)return{outcomes:[],skipped:[{reason:`agent ${s.agent.id} has a live executor`,sessionId:uuid}]};let rows=await(await getConnection())`
4051
4051
  SELECT current_executor_id FROM agents WHERE id = ${s.agent.id} LIMIT 1
4052
- `,agentRow={id:s.agent.id,repo_path:s.realCwd,team:s.agent.team,custom_name:s.agent.customName,current_executor_id:rows[0]?.current_executor_id??null};try{return{outcomes:[await attachOrphan({agentRow,agentLive:!1,candidate})],skipped:[]}}catch(err){return{outcomes:[],skipped:[{reason:err instanceof Error?err.message:String(err),sessionId:uuid}]}}}return{outcomes:[],skipped:[{reason:"session UUID not found among orphans",sessionId:uuid}]}}async function recoverOrphansCommand(options={}){let projectsRoot=resolveProjectsRoot();if(!existsSync24(projectsRoot)){console.log(`No Claude projects directory at ${projectsRoot} \u2014 nothing to scan.`);return}if(!await isAvailable())console.error("Genie database is unreachable. Start it with `genie serve` and retry."),process.exit(1);if(options.apply&&!options.newest&&!options.uuid)console.error("--apply requires either --newest (attach the newest orphan per dir) or --uuid <session-id>."),process.exit(2);let summaries=await scanOrphans({dir:options.dir});if(!options.apply){renderSummary(summaries);return}let outcomes=[],skipped=[];if(options.uuid)({outcomes,skipped}=await applyUuid(summaries,options.uuid));else if(options.newest)({outcomes,skipped}=await applyNewest(summaries));renderApplyReport(outcomes,skipped)}init_setup();init_shortcuts();import{existsSync as existsSync27}from"fs";import{homedir as homedir27}from"os";import{join as join33}from"path";async function shortcutsShowCommand(){displayShortcuts();let home=homedir27(),tmuxConf=join33(home,".tmux.conf"),zshrc=join33(home,".zshrc"),bashrc=join33(home,".bashrc");if(console.log("Installation status:"),isShortcutsInstalled(tmuxConf))console.log(" \x1B[32m\u2713\x1B[0m tmux.conf");else console.log(" \x1B[33m-\x1B[0m tmux.conf");let shellRc=existsSync27(zshrc)?zshrc:bashrc;if(isShortcutsInstalled(shellRc))console.log(` \x1B[32m\u2713\x1B[0m ${shellRc.replace(home,"~")}`);else console.log(` \x1B[33m-\x1B[0m ${shellRc.replace(home,"~")}`);console.log(),console.log("Run \x1B[36mgenie shortcuts install\x1B[0m to install shortcuts."),console.log("Run \x1B[36mgenie shortcuts uninstall\x1B[0m to remove shortcuts."),console.log()}async function shortcutsInstallCommand(){await installShortcuts()}async function shortcutsUninstallCommand(){await uninstallShortcuts()}init_esm14();init_claude_settings();init_genie_config2();import{existsSync as existsSync28,lstatSync,rmSync as rmSync2,unlinkSync as unlinkSync8}from"fs";import{homedir as homedir28}from"os";import{join as join34}from"path";var ORCHESTRATION_RULES_PATH=join34(homedir28(),".claude","rules","genie-orchestration.md"),LOCAL_BIN=join34(homedir28(),".local","bin"),SYMLINKS=["genie","term"];function isGenieSymlink(path3){try{if(!existsSync28(path3))return!1;if(!lstatSync(path3).isSymbolicLink())return!1;return!0}catch{return!1}}function removeSymlinks(){let removed=[];for(let name of SYMLINKS){let symlinkPath=join34(LOCAL_BIN,name);if(isGenieSymlink(symlinkPath))try{unlinkSync8(symlinkPath),removed.push(name)}catch{}}return removed}function tryRemoveStep(label,successMsg,fn){console.log(`\x1B[2m${label}\x1B[0m`);try{fn(),console.log(` \x1B[32m+\x1B[0m ${successMsg}`)}catch(error){let message=error instanceof Error?error.message:String(error);console.log(` \x1B[33m!\x1B[0m ${label.replace("...","")} failed: ${message}`)}}function performUninstall(hasHookScript,existingSymlinks,genieDir,hasGenieDir){if(hasHookScript)tryRemoveStep("Removing hook script...","Hook script removed",()=>removeHookScript());if(existingSymlinks.length>0){console.log("\x1B[2mRemoving symlinks...\x1B[0m");let removed=removeSymlinks();if(removed.length>0)console.log(` \x1B[32m+\x1B[0m Removed: ${removed.join(", ")}`)}if(existsSync28(ORCHESTRATION_RULES_PATH))tryRemoveStep("Removing orchestration rules...","Orchestration rules removed (~/.claude/rules/genie-orchestration.md)",()=>unlinkSync8(ORCHESTRATION_RULES_PATH));if(hasGenieDir)tryRemoveStep("Removing genie directory...","Directory removed",()=>rmSync2(genieDir,{recursive:!0,force:!0}))}async function uninstallCommand(){console.log(),console.log("\x1B[1m\x1B[33m Uninstall Genie CLI\x1B[0m"),console.log();let genieDir=getGenieDir(),hasGenieDir=existsSync28(genieDir),hasHookScript=hookScriptExists(),hasOrchestrationRules=existsSync28(ORCHESTRATION_RULES_PATH),existingSymlinks=SYMLINKS.filter((name)=>isGenieSymlink(join34(LOCAL_BIN,name)));if(console.log("\x1B[2mThis will remove:\x1B[0m"),hasHookScript)console.log(" \x1B[31m-\x1B[0m Hook script (~/.claude/hooks/genie-bash-hook.sh)");if(hasOrchestrationRules)console.log(" \x1B[31m-\x1B[0m Orchestration rules (~/.claude/rules/genie-orchestration.md)");if(hasGenieDir)console.log(` \x1B[31m-\x1B[0m Genie directory (${contractPath(genieDir)})`);if(existingSymlinks.length>0)console.log(` \x1B[31m-\x1B[0m Symlinks from ~/.local/bin: ${existingSymlinks.join(", ")}`);if(console.log(),!hasGenieDir&&!hasHookScript&&!hasOrchestrationRules&&existingSymlinks.length===0){console.log("\x1B[33mNothing to uninstall.\x1B[0m"),console.log();return}if(!await esm_default4({message:"Are you sure you want to uninstall Genie CLI?",default:!1})){console.log(),console.log("\x1B[2mUninstall cancelled.\x1B[0m"),console.log();return}console.log(),performUninstall(hasHookScript,existingSymlinks,genieDir,hasGenieDir),console.log(),console.log("\x1B[32m+\x1B[0m Genie CLI uninstalled."),console.log(),console.log("\x1B[2mNote: If you installed via npm/bun, also run:\x1B[0m"),console.log(" \x1B[36mbun remove -g @automagik/genie\x1B[0m"),console.log(" \x1B[2mor\x1B[0m"),console.log(" \x1B[36mnpm uninstall -g @automagik/genie\x1B[0m"),console.log()}init_genie_config2();init_version();import{execSync as execSync3,spawn as spawn3}from"child_process";import{chmodSync as chmodSync2,closeSync as closeSync3,copyFileSync as copyFileSync3,existsSync as existsSync30,mkdirSync as mkdirSync15,openSync as openSync3,readFileSync as readFileSync22,readSync as readSync2,readdirSync as readdirSync10,readlinkSync,rmSync as rmSync3,statSync as statSync8,writeFileSync as writeFileSync13}from"fs";import{chmod,copyFile,mkdir as mkdir5,unlink as unlink2}from"fs/promises";import{homedir as homedir29}from"os";import{join as join35}from"path";var REGISTRY=[];async function cleanupLegacyArtifacts(skipList,registry=REGISTRY){let entries=[];for(let artifact of registry){if(skipList.has(artifact.name)){entries.push({name:artifact.name,outcome:"skipped",removed:[],warnings:[]});continue}if(!await artifact.detect()){entries.push({name:artifact.name,outcome:"absent",removed:[],warnings:[]});continue}let result2=await artifact.cleanup();entries.push({name:artifact.name,outcome:"cleaned",removed:result2.removed,warnings:result2.warnings})}return{entries}}function parseSkipCleanupFlag(value){let skip=new Set;if(!value)return skip;for(let part of value.split(",")){let name=part.trim();if(name)skip.add(name)}return skip}var GENIE_HOME2=process.env.GENIE_HOME||join35(homedir29(),".genie"),GENIE_SRC=join35(GENIE_HOME2,"src"),GENIE_BIN=join35(GENIE_HOME2,"bin"),LOCAL_BIN2=join35(homedir29(),".local","bin"),TRUTHY=new Set(["1","true","yes","on"]),UPDATE_DIAGNOSTIC_SCHEMA_VERSION=2,VERIFY_PROBE_DEADLINE_MS=15000,VERIFY_PROBE_POLL_INTERVAL_MS=500,FETCH_LATEST_TIMEOUT_MS=5000;function normalizeVersion(value){let trimmed=value.trim(),plusIdx=trimmed.indexOf("+");return plusIdx===-1?trimmed:trimmed.slice(0,plusIdx)}function decideVerify(args){if(args.skipReason)return{kind:"skipped",reason:args.skipReason};if(args.serverHealthBody===null)return{kind:"health-unreachable",endpoint:args.endpoint};let rawServerVersion=args.serverHealthBody.version??null,diskVersion=rawServerVersion===null?null:normalizeVersion(rawServerVersion),pid=args.serverHealthBody.daemonPid??null;if(args.serverHealthBody.daemonInodeStale===!0)return{kind:"daemon-stale-inode",diskVersion,pid:pid??0,cwd:args.serverHealthBody.daemonCwd??""};return{kind:"ok",version:diskVersion,pid}}function shortCircuitIfCurrent(currentVersion,latestVersion){if(!latestVersion)return!1;return normalizeVersion(currentVersion)===normalizeVersion(latestVersion)}async function fetchLatestVersion(channel){let candidates=[{cmd:"npm",args:["view",`@automagik/genie@${channel}`,"version"]},{cmd:"bunx",args:["npm","view",`@automagik/genie@${channel}`,"version"]}];for(let{cmd,args}of candidates){let result2=await runCommandSilent(cmd,args,void 0,FETCH_LATEST_TIMEOUT_MS);if(!result2.success)continue;let trimmed=result2.output.trim();if(!trimmed)continue;let lines=trimmed.split(/\r?\n/).filter(Boolean),tokens2=lines[lines.length-1].split(/\s+/),candidate=tokens2[tokens2.length-1].replace(/^['"]|['"]$/g,"");if(/^\d+\.\d+/.test(candidate))return candidate}return null}async function promptConfirm(question){if(!process.stdin.isTTY||!process.stdout.isTTY)return!0;return process.stdout.write(`${question} [Y/n] `),new Promise((resolve6)=>{let onData=(chunk)=>{process.stdin.removeListener("data",onData),process.stdin.pause();let answer=chunk.toString("utf-8").trim().toLowerCase();if(answer===""||answer==="y"||answer==="yes")resolve6(!0);else resolve6(!1)};process.stdin.resume(),process.stdin.once("data",onData)})}function shouldAutoConfirm(opts){if(opts.yes)return!0;return isTruthyEnv(process.env.GENIE_UPDATE_YES)}var VERIFY_PROBE_ENDPOINT="pgserve status --json + ~/.genie/serve.pid";function readDaemonCwd(pid){if(process.platform!=="linux")return null;try{let cwd=readlinkSync(`/proc/${pid}/cwd`);return{cwd,staleInode:cwd.endsWith(" (deleted)")}}catch{return null}}function readInstalledPackageVersion(){let candidates=[join35(homedir29(),".bun","install","global","node_modules","@automagik","genie","package.json")],npmPrefix=safeExec("npm prefix -g",1500);if(npmPrefix)candidates.push(join35(npmPrefix,"lib","node_modules","@automagik","genie","package.json"));for(let path3 of candidates)try{let pkg=JSON.parse(readFileSync22(path3,"utf-8"));if(typeof pkg.version==="string"&&/^\d+\.\d+/.test(pkg.version))return pkg.version}catch{}return null}async function readServerHealth(){if(!(await runCommandSilent("pgserve",["status","--json"],void 0,3000)).success)return null;let pidPath=join35(GENIE_HOME2,"serve.pid"),rawPid=safeRead(pidPath,32);if(!rawPid)return null;let pid=Number.parseInt(rawPid.trim(),10);if(!Number.isFinite(pid)||pid<=0)return null;try{process.kill(pid,0)}catch{return null}let cwdInfo=readDaemonCwd(pid);return{version:readInstalledPackageVersion()??VERSION,daemonInodeStale:cwdInfo?.staleInode??!1,daemonPid:pid,daemonCwd:cwdInfo?.cwd}}async function pollHealth(readHealth,deadlineMs,intervalMs){let startedAt=Date.now();while(Date.now()-startedAt<deadlineMs){let body=null;try{body=await readHealth()}catch{}if(body!==null)return body;await new Promise((r)=>setTimeout(r,intervalMs))}return null}async function runVerifyProbe(opts={}){if(opts.skipReason)return decideVerify({serverHealthBody:null,endpoint:VERIFY_PROBE_ENDPOINT,skipReason:opts.skipReason});let reader=opts.readHealth??readServerHealth,deadline=opts.deadlineMs??VERIFY_PROBE_DEADLINE_MS,interval=opts.intervalMs??VERIFY_PROBE_POLL_INTERVAL_MS,body=await pollHealth(reader,deadline,interval);return decideVerify({serverHealthBody:body,endpoint:VERIFY_PROBE_ENDPOINT})}async function pm2GenieServe(){let result2=await runCommandSilent("pm2",["jlist"],void 0,3000);if(!result2.success)return null;try{let list2=JSON.parse(result2.output),candidates=pm2ProcessNameCandidates();for(let name of candidates){let entry2=list2.find((p)=>p.name===name);if(!entry2)continue;if(typeof entry2.pid!=="number"||entry2.pid<=0)continue;if(entry2.pm2_env?.status!=="online")continue;return{name,pid:entry2.pid,restartCount:entry2.pm2_env?.restart_time??0}}return null}catch{return null}}async function restartServeIfStale(){let before=await pm2GenieServe();if(!before)return null;let cwdInfo=readDaemonCwd(before.pid);if(!cwdInfo||!cwdInfo.staleInode)return null;log(`Restarting pm2 ${before.name} (stale inode detected: ${cwdInfo.cwd})`);let configPath2=null;try{configPath2=regenerateEcosystemConfig()}catch(err){let reason=err instanceof Error?err.message:String(err);error(`Could not regenerate pm2 ecosystem config (${reason}); falling back to plain restart`)}let restartArgs=configPath2?["startOrReload",configPath2,"--update-env"]:["restart",before.name,"--update-env"];if(!(await runCommandSilent("pm2",restartArgs,void 0,1e4)).success)return error(`pm2 ${restartArgs[0]} ${before.name} failed; daemon will keep serving pre-update bytes until manually restarted`),null;let deadline=Date.now()+1e4;while(Date.now()<deadline){let after=await pm2GenieServe();if(after&&(after.pid!==before.pid||after.restartCount>before.restartCount))return success(`pm2 ${after.name} restarted (pid ${before.pid} \u2192 ${after.pid})`),{oldPid:before.pid,newPid:after.pid};await new Promise((r)=>setTimeout(r,500))}return error("pm2 restart did not produce a new pid within 10s \u2014 verify probe will surface the stale state"),null}function formatVerifyBanner(result2){let lines=[];switch(result2.kind){case"ok":{let versionLabel=result2.version?`v${result2.version}`:"version unknown",pidSuffix=result2.pid?` (pid ${result2.pid}, healthy)`:" (healthy)";lines.push(`${colorize("\x1B[32m","\x1B[0m","\u2714")} Genie ${versionLabel}${pidSuffix}`);break}case"health-unreachable":lines.push(`${colorize("\x1B[31m","\x1B[0m","\u2716")} Genie server unreachable (probe: ${result2.endpoint})`),lines.push(`${colorize("\x1B[2m","\x1B[0m"," fix: pm2 restart Genie (or `genie install` if not yet supervised)")}`);break;case"daemon-stale-inode":{let versionLabel=result2.diskVersion?`v${result2.diskVersion}`:"version unknown";lines.push(`${colorize("\x1B[31m","\x1B[0m","\u2716")} Genie ${versionLabel} \u2014 daemon serving stale bytes (pid ${result2.pid})`),lines.push(`${colorize("\x1B[2m","\x1B[0m",` cwd: ${result2.cwd}`)}`),lines.push(`${colorize("\x1B[2m","\x1B[0m"," fix: pm2 restart Genie --update-env")}`);break}case"auth-invalid":lines.push(`${colorize("\x1B[31m","\x1B[0m","\u2716")} Auth: invalid`);break;case"skipped":lines.push(`${colorize("\x1B[2m","\x1B[0m",`\xB7 Genie verify skipped: ${result2.reason} (CLI in-process v${VERSION})`)}`);break}return lines}function colorEnabled(){if(process.env.NO_COLOR)return!1;if(process.env.FORCE_COLOR&&process.env.FORCE_COLOR!=="0")return!0;return Boolean(process.stdout.isTTY)}function colorize(open4,close,text){return colorEnabled()?`${open4}${text}${close}`:text}function log(message){console.log(`${colorize("\x1B[32m","\x1B[0m","\u25B8")} ${message}`)}function success(message){console.log(`${colorize("\x1B[32m","\x1B[0m","\u2714")} ${message}`)}function error(message){console.log(`${colorize("\x1B[31m","\x1B[0m","\u2716")} ${message}`)}function formatDuration2(ms){if(ms<1000)return`${ms}ms`;return`${(ms/1000).toFixed(1)}s`}function isTruthyEnv(value){return value!==void 0&&TRUTHY.has(value.trim().toLowerCase())}async function withTemporaryEnv(key,value,fn){let previous=process.env[key];process.env[key]=value;try{return await fn()}finally{if(previous===void 0)delete process.env[key];else process.env[key]=previous}}function safeExec(command,timeoutMs=1500){try{return execSync3(command,{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:timeoutMs}).trim()}catch(err){let stdout=err.stdout;if(typeof stdout==="string"&&stdout.trim())return stdout.trim();return""}}function safeRead(path3,maxChars=4000){try{let value=readFileSync22(path3,"utf-8");if(value.length<=maxChars)return value;return value.slice(value.length-maxChars)}catch{return null}}function tailLines(path3,maxBytes=64000,maxLines=200){let fd=null;try{let stat4=statSync8(path3),bytesToRead=Math.min(stat4.size,maxBytes),buffer2=Buffer.alloc(bytesToRead);return fd=openSync3(path3,"r"),readSync2(fd,buffer2,0,bytesToRead,Math.max(0,stat4.size-bytesToRead)),buffer2.toString("utf-8").split(/\r?\n/).map((line)=>line.trim()).filter(Boolean).slice(-maxLines)}catch{return[]}finally{if(fd!==null)try{closeSync3(fd)}catch{}}}function summarizeJsonlSignals(path3){let signals2=new Map;for(let line of tailLines(path3))try{let event=JSON.parse(line),level=typeof event.level==="string"?event.level:"unknown";if(level!=="error"&&level!=="warn")continue;let name=typeof event.event==="string"?event.event:"unknown",key=`${level}:${name}`,existing=signals2.get(key)??{level,event:name,count:0};if(existing.count++,typeof event.timestamp==="string")existing.lastTimestamp=event.timestamp;if(typeof event.error==="string")existing.lastError=event.error;signals2.set(key,existing)}catch{}return[...signals2.values()].sort((a,b2)=>b2.count-a.count).slice(0,10)}async function collectUpdateDiagnostics(ctx,maintenance,extras){let logsDir=join35(GENIE_HOME2,"logs");mkdirSync15(logsDir,{recursive:!0});let generatedAt=new Date().toISOString(),safeStamp=generatedAt.replace(/[:.]/g,"-"),path3=join35(logsDir,`update-diagnostics-${safeStamp}.json`),schedulerLog=join35(logsDir,"scheduler.log"),tuiCrashLog=join35(logsDir,"tui-crash.log"),signals2=summarizeJsonlSignals(schedulerLog),diagnostics={schemaVersion:UPDATE_DIAGNOSTIC_SCHEMA_VERSION,cli:"genie",generatedAt,verify:extras.verify,cleanups:extras.cleanups,update:ctx,runtime:{platform:process.platform,arch:process.arch,cwd:process.cwd(),node:process.version,bun:(await runCommandSilent("bun",["--version"])).output.trim()||null,npm:(await runCommandSilent("npm",["--version"])).output.trim()||null,genie:{which:(await runCommandSilent("which",["genie"])).output.trim()||null,tuiDisabled:isTruthyEnv(process.env.GENIE_TUI_DISABLE),updateSkipMaintenance:isTruthyEnv(process.env.GENIE_UPDATE_SKIP_MAINTENANCE)}},paths:{genieHome:GENIE_HOME2,logsDir,servePid:safeRead(join35(GENIE_HOME2,"serve.pid"),200),pgservePort:safeRead(join35(GENIE_HOME2,"pgserve.port"),200),schedulerLog,tuiCrashLog},processSnapshot:{genie:safeExec("ps -axo pid,ppid,pgid,stat,pcpu,pmem,etime,command -r | rg -i 'dist/genie.js|/src/genie.ts|pgserve|postgres -D .*\\.genie/data/pgserve|tmux -L genie-tui|bun' || true",2000)||null,tuiTmux:safeExec("tmux -L genie-tui ls 2>/dev/null || true",1000)||null},maintenance:{...maintenance,pgAutostartDisabled:!0,legend:{"[ok]":"healthy","[fix]":"fixed during maintenance","[--]":"skipped/non-blocking","[!!]":"operator action needed; update still completed"}},recentLogSignals:{scheduler:signals2,schedulerTail:tailLines(schedulerLog,32000,80),tuiCrashTail:tailLines(tuiCrashLog,32000,80)}};return writeFileSync13(path3,`${JSON.stringify(diagnostics,null,2)}
4053
- `),{path:path3,signals:signals2}}async function runCommand(command,args,cwd){return new Promise((resolve6)=>{let output=[],child=spawn3(command,args,{cwd,stdio:["inherit","pipe","pipe"],env:{...process.env,FORCE_COLOR:"1"}});child.stdout?.on("data",(data)=>{let str2=data.toString();output.push(str2),process.stdout.write(str2)}),child.stderr?.on("data",(data)=>{let str2=data.toString();output.push(str2),process.stderr.write(str2)}),child.on("close",(code)=>{resolve6({success:code===0,output:output.join("")})}),child.on("error",(err)=>{error(err.message),resolve6({success:!1,output:err.message})})})}async function getGitInfo(cwd){try{let branchResult=await runCommandSilent("git",["rev-parse","--abbrev-ref","HEAD"],cwd),commitResult=await runCommandSilent("git",["rev-parse","--short","HEAD"],cwd),dateResult=await runCommandSilent("git",["log","-1","--format=%ci"],cwd);if(branchResult.success&&commitResult.success&&dateResult.success)return{branch:branchResult.output.trim(),commit:commitResult.output.trim(),commitDate:dateResult.output.trim().split(" ")[0]}}catch{}return null}async function runCommandSilent(command,args,cwd,timeoutMs=4000){return new Promise((resolve6)=>{let output=[],settled=!1,child=spawn3(command,args,{cwd,stdio:["inherit","pipe","pipe"]}),timer2=setTimeout(()=>{if(settled)return;settled=!0,child.kill("SIGTERM"),resolve6({success:!1,output:`Timed out after ${timeoutMs}ms`})},timeoutMs);child.stdout?.on("data",(data)=>{output.push(data.toString())}),child.stderr?.on("data",(data)=>{output.push(data.toString())}),child.on("close",(code)=>{if(settled)return;settled=!0,clearTimeout(timer2),resolve6({success:code===0,output:output.join("")})}),child.on("error",(err)=>{if(settled)return;settled=!0,clearTimeout(timer2),resolve6({success:!1,output:err.message})})})}function detectFromBinaryPath(path3){let resolved=path3;try{resolved=__require("fs").realpathSync(path3)}catch{}if(resolved.includes(".bun"))return"bun";if(resolved.includes("node_modules"))return"npm";if(path3===join35(LOCAL_BIN2,"genie")||resolved.startsWith(GENIE_BIN))return"source";return null}async function detectInstallationType(){let whichResult=await runCommandSilent("which",["genie"]);if(whichResult.success){let detected=detectFromBinaryPath(whichResult.output.trim());if(detected)return detected}if(genieConfigExists())try{let config=await loadGenieConfig();if(config.installMethod)return config.installMethod}catch{}if(existsSync30(join35(GENIE_SRC,".git")))return"source";return(await runCommandSilent("which",["bun"])).success?"bun":"npm"}async function updateViaBun(channel){try{__require("fs").unlinkSync(join35(homedir29(),".bun","install","global","bun.lock"))}catch{}if(log(`Updating via bun (channel: ${channel})...`),!(await runCommand("bun",["add","-g",`@automagik/genie@${channel}`])).success)return error("Failed to update via bun"),!1;return console.log(),success(`Genie CLI updated via bun (${channel})!`),!0}async function updateViaNpm(channel){if(log(`Updating via npm (channel: ${channel})...`),!(await runCommand("npm",["install","-g",`@automagik/genie@${channel}`])).success)return error("Failed to update via npm"),!1;return console.log(),success(`Genie CLI updated via npm (${channel})!`),!0}async function detectGlobalInstalls(){let found=new Set,[npmResult,bunResult]=await Promise.all([runCommandSilent("npm",["list","-g","@automagik/genie"]),runCommandSilent("bun",["pm","ls","-g"])]);if(npmResult.success&&!npmResult.output.includes("(empty)"))found.add("npm");if(bunResult.success&&bunResult.output.includes("@automagik/genie"))found.add("bun");return found}async function updateSource(){if(!existsSync30(GENIE_SRC))error(`Source install path not found: ${GENIE_SRC}`),console.error(" Detection picked the source-install path, but the directory does not exist."),console.error(" This usually means a stale install hint (config or ~/.genie/src/.git) is"),console.error(" pointing somewhere genuine. Either:"),console.error(` 1. Re-clone the source: git clone https://github.com/automagik-dev/genie ${GENIE_SRC}`),console.error(" 2. Update via package manager instead: genie update --next --via bun"),console.error(" 3. Inspect detection: genie doctor --update-detection"),process.exit(1);if(!existsSync30(join35(GENIE_SRC,".git")))error(`Source install path is not a git checkout: ${GENIE_SRC}`),console.error(` ${GENIE_SRC} exists but has no .git/. Cannot run \`git fetch\` from it.`),console.error(` Either delete ${GENIE_SRC} and re-clone, or update via package manager:`),console.error(" genie update --next --via bun"),process.exit(1);let beforeInfo=await getGitInfo(GENIE_SRC);if(beforeInfo)console.log(`Current: \x1B[2m${beforeInfo.branch}@${beforeInfo.commit} (${beforeInfo.commitDate})\x1B[0m`),console.log();if(log("Fetching latest changes..."),!(await runCommand("git",["fetch","origin"],GENIE_SRC)).success)error("Failed to fetch from origin"),process.exit(1);if(log("Resetting to origin/main..."),!(await runCommand("git",["reset","--hard","origin/main"],GENIE_SRC)).success)error("Failed to reset to origin/main"),process.exit(1);console.log();let afterInfo=await getGitInfo(GENIE_SRC);if(beforeInfo&&afterInfo&&beforeInfo.commit===afterInfo.commit){success("Already up to date!"),console.log();return}if(log("Installing dependencies..."),!(await runCommand("bun",["install"],GENIE_SRC)).success)error("Failed to install dependencies"),process.exit(1);if(console.log(),log("Building..."),!(await runCommand("bun",["run","build"],GENIE_SRC)).success)error("Failed to build"),process.exit(1);console.log(),log("Installing binaries...");try{await mkdir5(GENIE_BIN,{recursive:!0}),await mkdir5(LOCAL_BIN2,{recursive:!0});let binaries=["genie.js","term.js"],names=["genie","term"];for(let i2=0;i2<binaries.length;i2++){let src=join35(GENIE_SRC,"dist",binaries[i2]),binDest=join35(GENIE_BIN,binaries[i2]),linkDest=join35(LOCAL_BIN2,names[i2]);await copyFile(src,binDest),await chmod(binDest,493),await symlinkOrCopy(binDest,linkDest)}for(let legacy of["claudio.js","claudio"]){let legacyBin=join35(GENIE_BIN,legacy),legacyLink=join35(LOCAL_BIN2,legacy);try{await unlink2(legacyBin)}catch{}try{await unlink2(legacyLink)}catch{}}success("Binaries installed")}catch(err){error(`Failed to install binaries: ${err}`),process.exit(1)}if(console.log(),console.log("\x1B[2m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m"),success("Genie CLI updated successfully!"),console.log(),afterInfo)console.log(`Version: \x1B[36m${afterInfo.branch}@${afterInfo.commit}\x1B[0m (${afterInfo.commitDate})`),console.log()}async function symlinkOrCopy(src,dest){let{symlink:symlink2,unlink:unlink3}=await import("fs/promises");try{if(existsSync30(dest))await unlink3(dest);await symlink2(src,dest)}catch{await copyFile(src,dest)}}var FRAMEWORK_MARKER_FILES=new Set([".orphaned_at"]);function copyDirSync(src,dest){mkdirSync15(dest,{recursive:!0});for(let entry2 of readdirSync10(src,{withFileTypes:!0})){if(FRAMEWORK_MARKER_FILES.has(entry2.name))continue;let srcPath=join35(src,entry2.name),destPath=join35(dest,entry2.name);if(entry2.isDirectory())copyDirSync(srcPath,destPath);else copyFileSync3(srcPath,destPath)}}async function resolveGlobalPkgDir(installType){if(installType==="bun"){let bunPath=join35(homedir29(),".bun","install","global","node_modules","@automagik","genie");if(existsSync30(bunPath))return bunPath}if(installType==="npm"){let npmRootResult=await runCommandSilent("npm",["root","-g"]);if(npmRootResult.success){let npmPath=join35(npmRootResult.output.trim(),"@automagik","genie");if(existsSync30(npmPath))return npmPath}}let bunFallback=join35(homedir29(),".bun","install","global","node_modules","@automagik","genie");if(existsSync30(bunFallback))return bunFallback;let npmRootFallback=await runCommandSilent("npm",["root","-g"]);if(npmRootFallback.success){let npmPath=join35(npmRootFallback.output.trim(),"@automagik","genie");if(existsSync30(npmPath))return npmPath}return null}function updatePluginRegistry(claudePlugins,cacheDir,version){let registryPath=join35(claudePlugins,"installed_plugins.json");try{if(!existsSync30(registryPath))return;let registry=JSON.parse(readFileSync22(registryPath,"utf-8")),entries=registry.plugins?.["genie@automagik"];if(!Array.isArray(entries))return;for(let entry2 of entries)if(entry2.scope==="user")entry2.installPath=cacheDir,entry2.version=version,entry2.lastUpdated=new Date().toISOString();writeFileSync13(registryPath,JSON.stringify(registry,null,2))}catch(err){log(`Registry update failed (non-fatal): ${err}`)}}function syncTmuxConf(tmuxScriptsSrc){mkdirSync15(GENIE_HOME2,{recursive:!0});let tmuxConfSrc=join35(tmuxScriptsSrc,"genie.tmux.conf"),tmuxConfDest=join35(GENIE_HOME2,"tmux.conf");if(existsSync30(tmuxConfSrc))try{copyFileSync3(tmuxConfSrc,tmuxConfDest),success(`Installed tmux config to ${tmuxConfDest}`);try{let{tmuxBin:tmuxBin2}=(init_ensure_tmux(),__toCommonJS(exports_ensure_tmux));execSync3(`${tmuxBin2()} -L genie source-file '${tmuxConfDest}'`,{stdio:"ignore"}),success("Reloaded genie tmux server configuration")}catch{}}catch{}let tuiConfSrc=join35(tmuxScriptsSrc,"tui-tmux.conf"),tuiConfDest=join35(GENIE_HOME2,"tui-tmux.conf");if(existsSync30(tuiConfSrc))try{copyFileSync3(tuiConfSrc,tuiConfDest),success(`Installed TUI tmux config to ${tuiConfDest}`)}catch{}let themeSrc=join35(tmuxScriptsSrc,".generated.theme.conf"),themeDest=join35(GENIE_HOME2,".generated.theme.conf");if(existsSync30(themeSrc))try{copyFileSync3(themeSrc,themeDest),success(`Installed tmux theme to ${themeDest}`)}catch{}let osc52Src=join35(tmuxScriptsSrc,"osc52-copy.sh"),osc52Dest=join35(GENIE_HOME2,"scripts","osc52-copy.sh");if(existsSync30(osc52Src))try{copyFileSync3(osc52Src,osc52Dest),chmodSync2(osc52Dest,493),success(`Installed OSC 52 clipboard helper to ${osc52Dest}`)}catch{}}function syncTmuxScripts(globalPkgDir){let tmuxScriptsSrc=join35(globalPkgDir,"scripts","tmux");if(!existsSync30(tmuxScriptsSrc))return;let scriptsDir=join35(GENIE_HOME2,"scripts");mkdirSync15(scriptsDir,{recursive:!0});let scriptCount=0;for(let entry2 of readdirSync10(tmuxScriptsSrc))if(entry2.endsWith(".sh")||entry2==="genie.tmux.conf"||entry2==="tui-tmux.conf"||entry2===".generated.theme.conf"){let src=join35(tmuxScriptsSrc,entry2),dest=join35(scriptsDir,entry2);copyFileSync3(src,dest);try{chmodSync2(dest,entry2.endsWith(".sh")?493:420)}catch{}scriptCount++}if(scriptCount>0)success(`Refreshed ${scriptCount} tmux scripts at ${scriptsDir}`);syncTmuxConf(tmuxScriptsSrc)}function syncMarketplaceVersion(claudePlugins,version){let marketplacePath=join35(claudePlugins,"marketplaces","automagik",".claude-plugin","marketplace.json");try{if(!existsSync30(marketplacePath))return;let data=JSON.parse(readFileSync22(marketplacePath,"utf-8"));if(Array.isArray(data.plugins)){for(let plugin of data.plugins)if(plugin.name==="genie")plugin.version=version}writeFileSync13(marketplacePath,JSON.stringify(data,null,2)),success(`Updated marketplace.json to v${version}`)}catch(err){log(`Marketplace version update failed (non-fatal): ${err}`)}}function syncPluginPackageVersion(claudePlugins,version){let pkgPath=join35(claudePlugins,"marketplaces","automagik","plugins","genie","package.json");try{if(!existsSync30(pkgPath))return;let data=JSON.parse(readFileSync22(pkgPath,"utf-8"));data.version=version,writeFileSync13(pkgPath,JSON.stringify(data,null,2)),success(`Updated plugin package.json to v${version}`)}catch(err){log(`Plugin package.json update failed (non-fatal): ${err}`)}}function syncSkillsSymlink(claudePlugins,version){let skillsLink=join35(claudePlugins,"marketplaces","automagik","plugins","genie","skills"),cacheSkills=join35("..","..","..","..","cache","automagik","genie",version,"skills");try{let{symlinkSync,unlinkSync:unlinkSync9,lstatSync:lstatSync2}=__require("fs");try{lstatSync2(skillsLink),unlinkSync9(skillsLink)}catch{}symlinkSync(cacheSkills,skillsLink),success(`Skills symlink \u2192 cache/${version}/skills`)}catch(err){log(`Skills symlink update failed (non-fatal): ${err}`)}}async function syncPlugin(installType){log("Syncing Claude Code plugin...");let globalPkgDir=await resolveGlobalPkgDir(installType);if(!globalPkgDir)return log("Could not find installed package \u2014 skipping plugin sync"),{skippedReason:"installed package not found"};let pluginSrc=join35(globalPkgDir,"plugins","genie");if(!existsSync30(pluginSrc))return log("Plugin source not found in package \u2014 skipping plugin sync"),{globalPkgDir,skippedReason:"plugin source not found in package"};let version;try{version=JSON.parse(readFileSync22(join35(globalPkgDir,"package.json"),"utf-8")).version}catch{return log("Could not read package version \u2014 skipping plugin sync"),{globalPkgDir,skippedReason:"could not read package version"}}let claudePlugins=join35(homedir29(),".claude","plugins"),cacheDir=join35(claudePlugins,"cache","automagik","genie",version);try{if(existsSync30(cacheDir))rmSync3(cacheDir,{recursive:!0,force:!0});copyDirSync(pluginSrc,cacheDir);let skillsSrc=join35(globalPkgDir,"skills");if(existsSync30(skillsSrc)&&!existsSync30(join35(cacheDir,"skills")))copyDirSync(skillsSrc,join35(cacheDir,"skills"))}catch(err){return error(`Failed to copy plugin: ${err}`),{version,globalPkgDir,cacheDir,skippedReason:`failed to copy plugin: ${err}`}}return updatePluginRegistry(claudePlugins,cacheDir,version),syncMarketplaceVersion(claudePlugins,version),syncPluginPackageVersion(claudePlugins,version),syncSkillsSymlink(claudePlugins,version),syncTmuxScripts(globalPkgDir),success(`Plugin synced to v${version}`),{version,globalPkgDir,cacheDir}}async function resolveChannel(options){if(options.next)return"next";if(options.stable)return"latest";if(genieConfigExists())try{let config=await loadGenieConfig();if(config.updateChannel)return config.updateChannel}catch{}return"latest"}async function persistChannel(channel){try{let config=await loadGenieConfig();config.updateChannel=channel,await saveGenieConfig(config)}catch{}}async function updateCommand(options={}){console.log(),console.log(`${colorize("\x1B[1m","\x1B[0m","\uD83E\uDDDE Genie CLI Update")}`),console.log(`${colorize("\x1B[2m","\x1B[0m","\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`),console.log();let cleanupSkipList=buildCleanupSkipList(options),noRestart=options.restart===!1||isTruthyEnv(process.env.GENIE_UPDATE_NO_RESTART),noVerify=options.verify===!1||isTruthyEnv(process.env.GENIE_UPDATE_NO_VERIFY),channel=await resolveChannel(options);if(options.next||options.stable)await persistChannel(channel);let latestVersion=await fetchLatestVersion(channel);if(shortCircuitIfCurrent(VERSION,latestVersion)){success(`Already up to date (v${normalizeVersion(VERSION)}, channel ${channel})`),console.log();return}let installType=await detectInstallationType();if(log(`Detected installation: ${installType}`),log(`Channel: ${channel}${channel==="next"?" (dev builds)":" (stable)"}`),latestVersion)log(`Update available: ${normalizeVersion(VERSION)} \u2192 ${normalizeVersion(latestVersion)}`);else log(`Registry version unavailable (proceeding with reinstall of channel ${channel})`);if(console.log(),installType==="unknown")error("No Genie CLI installation found"),console.log(),console.log("Install method not configured. Please reinstall genie:"),console.log(`${colorize("\x1B[36m","\x1B[0m"," curl -fsSL https://raw.githubusercontent.com/automagik-dev/genie/main/install.sh | bash")}`),console.log(),process.exit(1);if(!shouldAutoConfirm(options)){let proceedQuestion=latestVersion?`Update v${normalizeVersion(VERSION)} \u2192 v${normalizeVersion(latestVersion)}?`:`Reinstall channel "${channel}"?`;if(!await promptConfirm(proceedQuestion)){console.log(),log("Update declined."),console.log();return}}if(installType==="source"){await updateSource();return}let globalInstalls=await detectGlobalInstalls(),primaryMethod=installType;if(!(primaryMethod==="bun"?await updateViaBun(channel):await updateViaNpm(channel)))process.exit(1);let secondaryMethod=primaryMethod==="bun"?"npm":"bun";if(globalInstalls.has(secondaryMethod)){if(console.log(),log(`Also updating ${secondaryMethod}-global install...`),!(secondaryMethod==="bun"?await updateViaBun(channel):await updateViaNpm(channel)))error(`Secondary update via ${secondaryMethod} failed (non-blocking)`)}let plugin=await syncPlugin(installType),cleanupReport=await runLegacyCleanupSafe(cleanupSkipList);await runPostUpdateMaintenanceSafe({...options,noRestart,noVerify},{channel,installType,primaryMethod,globalInstalls:[...globalInstalls].sort(),plugin,latestVersion,cliVersion:VERSION},cleanupReport)}function buildCleanupSkipList(options){let skipList=parseSkipCleanupFlag(options.skipCleanup);if(options.sidecarCleanup===!1)skipList.add("nats-reply-sidecar"),log("--no-sidecar-cleanup (no-op for genie, retained for cross-CLI portability)");return skipList}async function runLegacyCleanupSafe(skipList){try{return await cleanupLegacyArtifacts(skipList)}catch(err){let msg=err instanceof Error?err.message:String(err);return log(`Legacy artifact cleanup failed (non-fatal): ${msg}`),{entries:[]}}}function printPostUpdateMaintenanceIntro(){console.log(),log("Running post-update maintenance..."),console.log(" Purpose: make first launch after update fast and collect upgrade health signals."),console.log(" Checks: runtime partitions, watchdog status, session backfill drift, zombie rows, team config orphans."),console.log(" PG policy: read-only; uses an already-running pgserve when available and will not auto-start it."),console.log(" Legend: [ok]=healthy, [fix]=fixed, [--]=skipped/non-blocking, [!!]=operator action needed.")}async function runMaintenanceWithCapturedLines(maintenanceLines){let{runPostUpdateMaintenance:runPostUpdateMaintenance2}=await Promise.resolve().then(() => (init_doctor(),exports_doctor));await withTemporaryEnv("GENIE_PG_NO_AUTOSTART","1",()=>runPostUpdateMaintenance2({log:(line)=>{maintenanceLines.push(line),console.log(line)}}))}function printDiagnosticsSummary(diagnostics){if(log("Post-update diagnostics captured."),console.log(` Report: ${diagnostics.path}`),console.log(" Include this file when opening a GitHub issue; it contains install metadata, step output,"),console.log(" local process state, and recent scheduler/TUI log signals."),diagnostics.signals.length===0)return;console.log(" Recent scheduler signals:");for(let signal of diagnostics.signals.slice(0,3)){let errorDetail=signal.lastError?` \u2014 ${signal.lastError}`:"";console.log(` ${signal.level}:${signal.event} \xD7${signal.count}${errorDetail}`)}}async function capturePostUpdateDiagnostics(diagnosticsCtx,maintenance,extras){if(!diagnosticsCtx)return;try{let diagnostics=await collectUpdateDiagnostics(diagnosticsCtx,maintenance,extras);printDiagnosticsSummary(diagnostics)}catch(err){let msg=err instanceof Error?err.message:String(err);log(`Post-update diagnostics capture failed (non-fatal): ${msg}`)}}function printVerifyBanner(result2){console.log();for(let line of formatVerifyBanner(result2))console.log(` ${line}`);console.log()}async function runPostUpdateMaintenanceSafe(options,diagnosticsCtx,cleanupReport){if(options.noRestart){log("--no-restart: skipping maintenance and verify probe.");let verify2=await runVerifyProbe({skipReason:"no-restart"});printVerifyBanner(verify2),await capturePostUpdateDiagnostics(diagnosticsCtx,{outcome:"completed",durationMs:0,lines:[]},{verify:verify2,cleanups:cleanupReport});return}if(options.skipMaintenance||isTruthyEnv(process.env.GENIE_UPDATE_SKIP_MAINTENANCE)){log("Skipping post-update maintenance (requested).");let verify2=await runVerifyProbe({skipReason:"no-restart"});printVerifyBanner(verify2),await capturePostUpdateDiagnostics(diagnosticsCtx,{outcome:"completed",durationMs:0,lines:[]},{verify:verify2,cleanups:cleanupReport});return}let startedAt=Date.now(),maintenanceLines=[],outcome="completed",maintenanceError;try{printPostUpdateMaintenanceIntro(),await runMaintenanceWithCapturedLines(maintenanceLines),success(`Post-update maintenance complete (${formatDuration2(Date.now()-startedAt)}).`)}catch(err){outcome="failed",maintenanceError=err instanceof Error?err.message:String(err),error(`Post-update maintenance skipped: ${maintenanceError}`)}await restartServeIfStaleSafe();let verify=options.noVerify?await runVerifyProbe({skipReason:"no-verify-flag"}):await runVerifyProbe();if(printVerifyBanner(verify),await capturePostUpdateDiagnostics(diagnosticsCtx,{outcome,durationMs:Date.now()-startedAt,lines:maintenanceLines,error:maintenanceError},{verify,cleanups:cleanupReport}),(verify.kind==="health-unreachable"||verify.kind==="daemon-stale-inode")&&!options.noVerify)process.exitCode=1}async function restartServeIfStaleSafe(){try{await restartServeIfStale()}catch(err){let msg=err instanceof Error?err.message:String(err);log(`Stale-serve restart skipped (non-fatal): ${msg}`)}}init_version();init_trust();init_trust();init_trust();import{execSync as execSync4}from"child_process";import{existsSync as existsSync32,mkdirSync as mkdirSync16,readFileSync as readFileSync24,renameSync as renameSync6,writeFileSync as writeFileSync14}from"fs";import{dirname as dirname14,isAbsolute,join as join37,resolve as resolve6}from"path";function resolveOriginUrl(repoRoot){try{return execSync4("git config --get remote.origin.url",{cwd:repoRoot,encoding:"utf-8"}).trim()||null}catch{return null}}function findRepoRoot(start){let current=start;while(current!=="/"){if(existsSync32(join37(current,".git")))return current;current=dirname14(current)}return null}function writeTrustFile(path3,file){let dir=dirname14(path3);if(!existsSync32(dir))mkdirSync16(dir,{recursive:!0});let sorted={version:1,entries:[...file.entries].sort((a,b2)=>a.path.localeCompare(b2.path))},serialized=`${JSON.stringify(sorted,null,2)}
4054
- `,tmpPath=`${path3}.tmp.${process.pid}`;writeFileSync14(tmpPath,serialized,"utf-8"),renameSync6(tmpPath,path3)}function runTrustList(trustPath){let current=readTrustFile(trustPath);if(current.entries.length===0){console.log(`(trust file empty: ${trustPath})`);return}console.log(`Trusted hooks (${current.entries.length}, from ${trustPath}):`);for(let entry2 of current.entries){let scope=entry2.scope==="repo"?`repo:${entry2.repoRemoteUrl??"?"}`:entry2.scope;if(console.log(` ${entry2.path}`),console.log(` scope: ${scope}`),console.log(` sha256: ${entry2.sha256}`),console.log(` trusted: ${entry2.trustedAt}`),entry2.capabilities&&entry2.capabilities.length>0)console.log(` caps: ${entry2.capabilities.join(", ")}`);if(entry2.note)console.log(` note: ${entry2.note}`)}}function resolveTrustScope(filePath,options){if(options.repo){let repoRoot=findRepoRoot(dirname14(filePath));if(!repoRoot)console.error(`Error: --repo passed but no .git directory found above ${filePath}`),process.exit(1);let remote=resolveOriginUrl(repoRoot);if(!remote)console.error(`Error: --repo passed but ${repoRoot} has no remote.origin.url`),process.exit(1);return{scope:"repo",repoRemoteUrl:remote}}if(options.team)return{scope:"team"};return{scope:"global"}}async function confirmTrustOrAbort(yes){if(yes||!process.stdin.isTTY)return;process.stdout.write("Confirm? (y/N) ");let buf=Buffer.alloc(8),read=0;try{read=(await import("fs")).readSync(0,buf,0,buf.length,null)}catch{console.error("Error: cannot read confirmation; pass --yes to trust non-interactively"),process.exit(1)}let answer=buf.subarray(0,read).toString().trim().toLowerCase();if(answer!=="y"&&answer!=="yes")console.log("Aborted."),process.exit(1)}async function runTrustAdd(target,options,trustPath){let filePath=isAbsolute(target)?target:resolve6(process.cwd(),target);if(!existsSync32(filePath))console.error(`Error: file not found: ${filePath}`),process.exit(1);if(!filePath.endsWith(".ts"))console.error(`Error: trust target must be a .ts file: ${filePath}`),process.exit(1);let{scope,repoRemoteUrl}=resolveTrustScope(filePath,options),sha=sha256OfFile(filePath),source=readFileSync24(filePath,"utf-8"),capabilities=parseCapabilities(source);if(console.log(`About to trust: ${filePath}`),console.log(` scope: ${scope==="repo"?`repo:${repoRemoteUrl}`:scope}`),console.log(` sha256: ${sha}`),capabilities.length>0)console.log(` caps: ${capabilities.join(", ")}`);if(options.note)console.log(` note: ${options.note}`);await confirmTrustOrAbort(options.yes??!1);let current=readTrustFile(trustPath),newEntry={path:filePath,sha256:sha,scope,repoRemoteUrl,trustedAt:new Date().toISOString(),note:options.note,capabilities:capabilities.length>0?capabilities:void 0},next={version:1,entries:[...current.entries.filter((e)=>e.path!==filePath),newEntry]};writeTrustFile(trustPath,next),console.log(`Trusted ${filePath} \u2192 ${trustPath}`)}async function trustAction(target,options){let trustPath=defaultTrustPath();if(!target)return runTrustList(trustPath);await runTrustAdd(target,options,trustPath)}function registerHookTrustCommand(parent){parent.command("trust [path]").description("Add a .ts hook file to the trust allowlist (or list current entries when [path] is omitted)").option("--repo","Scope to current repo (pinned to remote.origin.url)").option("--global","Scope globally (default)").option("--team <name>","Scope to a specific team directory").option("--note <text>","Free-form note saved with the entry").option("--yes","Skip the interactive confirmation prompt").action(trustAction)}import{appendFileSync as appendFileSync3,chmodSync as chmodSync3,mkdirSync as mkdirSync17,statSync as statSync9}from"fs";import{connect as connect2}from"net";import{homedir as homedir31}from"os";import{dirname as dirname15,join as join38}from"path";var PATTERNS=[{kind:"gh-token",re:/gh[ps]_[A-Za-z0-9]{30,}/g},{kind:"sk-token",re:/sk-[A-Za-z0-9-]{20,}/g},{kind:"glpat",re:/glpat-[A-Za-z0-9_-]{20,}/g},{kind:"hex",re:/\b[a-f0-9]{40,}\b/g}];function redactTokenShapes(text){if(text==null)return null;if(process.env.GENIE_HOOK_REDACTION==="off")return String(text);let out=String(text);for(let{kind,re}of PATTERNS)out=out.replace(re,`[REDACTED:${kind}]`);return out}function defaultSocketPath(){if(process.env.GENIE_HOOK_SOCK)return process.env.GENIE_HOOK_SOCK;let home=process.env.GENIE_HOME??join38(homedir31(),".genie");return join38(home,"hook.sock")}function fallbackLogPath2(){let home=process.env.GENIE_HOME??join38(homedir31(),".genie");return join38(home,"hook-fallback.log")}var MAX_FRAME_BYTES=1048576,FALLBACK_LOG_MAX_BYTES=104857600,DEFAULT_TIMEOUT_MS=5000;function readStdinSync(){let chunks=[],total=0,fd=0,buf=Buffer.alloc(65536);while(!0){let n;try{n=__require("fs").readSync(fd,buf,0,buf.length,null)}catch{break}if(n===0)break;if(chunks.push(Buffer.from(buf.subarray(0,n))),total+=n,total>MAX_FRAME_BYTES)break}return Buffer.concat(chunks,Math.min(total,MAX_FRAME_BYTES))}function summarizePayload(payload){try{let obj=JSON.parse(payload.toString("utf-8")),event=typeof obj.hook_event_name==="string"?obj.hook_event_name:null,tool=typeof obj.tool_name==="string"?obj.tool_name:null,command=null,ti=obj.tool_input;if(ti&&typeof ti.command==="string")command=ti.command.split(`
4052
+ `,agentRow={id:s.agent.id,repo_path:s.realCwd,team:s.agent.team,custom_name:s.agent.customName,current_executor_id:rows[0]?.current_executor_id??null};try{return{outcomes:[await attachOrphan({agentRow,agentLive:!1,candidate})],skipped:[]}}catch(err){return{outcomes:[],skipped:[{reason:err instanceof Error?err.message:String(err),sessionId:uuid}]}}}return{outcomes:[],skipped:[{reason:"session UUID not found among orphans",sessionId:uuid}]}}async function recoverOrphansCommand(options={}){let projectsRoot=resolveProjectsRoot();if(!existsSync24(projectsRoot)){console.log(`No Claude projects directory at ${projectsRoot} \u2014 nothing to scan.`);return}if(!await isAvailable())console.error("Genie database is unreachable. Start it with `genie serve` and retry."),process.exit(1);if(options.apply&&!options.newest&&!options.uuid)console.error("--apply requires either --newest (attach the newest orphan per dir) or --uuid <session-id>."),process.exit(2);let summaries=await scanOrphans({dir:options.dir});if(!options.apply){renderSummary(summaries);return}let outcomes=[],skipped=[];if(options.uuid)({outcomes,skipped}=await applyUuid(summaries,options.uuid));else if(options.newest)({outcomes,skipped}=await applyNewest(summaries));renderApplyReport(outcomes,skipped)}init_setup();init_shortcuts();import{existsSync as existsSync27}from"fs";import{homedir as homedir27}from"os";import{join as join33}from"path";async function shortcutsShowCommand(){displayShortcuts();let home=homedir27(),tmuxConf=join33(home,".tmux.conf"),zshrc=join33(home,".zshrc"),bashrc=join33(home,".bashrc");if(console.log("Installation status:"),isShortcutsInstalled(tmuxConf))console.log(" \x1B[32m\u2713\x1B[0m tmux.conf");else console.log(" \x1B[33m-\x1B[0m tmux.conf");let shellRc=existsSync27(zshrc)?zshrc:bashrc;if(isShortcutsInstalled(shellRc))console.log(` \x1B[32m\u2713\x1B[0m ${shellRc.replace(home,"~")}`);else console.log(` \x1B[33m-\x1B[0m ${shellRc.replace(home,"~")}`);console.log(),console.log("Run \x1B[36mgenie shortcuts install\x1B[0m to install shortcuts."),console.log("Run \x1B[36mgenie shortcuts uninstall\x1B[0m to remove shortcuts."),console.log()}async function shortcutsInstallCommand(){await installShortcuts()}async function shortcutsUninstallCommand(){await uninstallShortcuts()}init_esm14();init_claude_settings();init_genie_config2();import{existsSync as existsSync28,lstatSync,rmSync as rmSync2,unlinkSync as unlinkSync8}from"fs";import{homedir as homedir28}from"os";import{join as join34}from"path";var ORCHESTRATION_RULES_PATH=join34(homedir28(),".claude","rules","genie-orchestration.md"),LOCAL_BIN=join34(homedir28(),".local","bin"),SYMLINKS=["genie","term"];function isGenieSymlink(path3){try{if(!existsSync28(path3))return!1;if(!lstatSync(path3).isSymbolicLink())return!1;return!0}catch{return!1}}function removeSymlinks(){let removed=[];for(let name of SYMLINKS){let symlinkPath=join34(LOCAL_BIN,name);if(isGenieSymlink(symlinkPath))try{unlinkSync8(symlinkPath),removed.push(name)}catch{}}return removed}function tryRemoveStep(label,successMsg,fn){console.log(`\x1B[2m${label}\x1B[0m`);try{fn(),console.log(` \x1B[32m+\x1B[0m ${successMsg}`)}catch(error){let message=error instanceof Error?error.message:String(error);console.log(` \x1B[33m!\x1B[0m ${label.replace("...","")} failed: ${message}`)}}function performUninstall(hasHookScript,existingSymlinks,genieDir,hasGenieDir){if(hasHookScript)tryRemoveStep("Removing hook script...","Hook script removed",()=>removeHookScript());if(existingSymlinks.length>0){console.log("\x1B[2mRemoving symlinks...\x1B[0m");let removed=removeSymlinks();if(removed.length>0)console.log(` \x1B[32m+\x1B[0m Removed: ${removed.join(", ")}`)}if(existsSync28(ORCHESTRATION_RULES_PATH))tryRemoveStep("Removing orchestration rules...","Orchestration rules removed (~/.claude/rules/genie-orchestration.md)",()=>unlinkSync8(ORCHESTRATION_RULES_PATH));if(hasGenieDir)tryRemoveStep("Removing genie directory...","Directory removed",()=>rmSync2(genieDir,{recursive:!0,force:!0}))}async function uninstallCommand(){console.log(),console.log("\x1B[1m\x1B[33m Uninstall Genie CLI\x1B[0m"),console.log();let genieDir=getGenieDir(),hasGenieDir=existsSync28(genieDir),hasHookScript=hookScriptExists(),hasOrchestrationRules=existsSync28(ORCHESTRATION_RULES_PATH),existingSymlinks=SYMLINKS.filter((name)=>isGenieSymlink(join34(LOCAL_BIN,name)));if(console.log("\x1B[2mThis will remove:\x1B[0m"),hasHookScript)console.log(" \x1B[31m-\x1B[0m Hook script (~/.claude/hooks/genie-bash-hook.sh)");if(hasOrchestrationRules)console.log(" \x1B[31m-\x1B[0m Orchestration rules (~/.claude/rules/genie-orchestration.md)");if(hasGenieDir)console.log(` \x1B[31m-\x1B[0m Genie directory (${contractPath(genieDir)})`);if(existingSymlinks.length>0)console.log(` \x1B[31m-\x1B[0m Symlinks from ~/.local/bin: ${existingSymlinks.join(", ")}`);if(console.log(),!hasGenieDir&&!hasHookScript&&!hasOrchestrationRules&&existingSymlinks.length===0){console.log("\x1B[33mNothing to uninstall.\x1B[0m"),console.log();return}if(!await esm_default4({message:"Are you sure you want to uninstall Genie CLI?",default:!1})){console.log(),console.log("\x1B[2mUninstall cancelled.\x1B[0m"),console.log();return}console.log(),performUninstall(hasHookScript,existingSymlinks,genieDir,hasGenieDir),console.log(),console.log("\x1B[32m+\x1B[0m Genie CLI uninstalled."),console.log(),console.log("\x1B[2mNote: If you installed via npm/bun, also run:\x1B[0m"),console.log(" \x1B[36mbun remove -g @automagik/genie\x1B[0m"),console.log(" \x1B[2mor\x1B[0m"),console.log(" \x1B[36mnpm uninstall -g @automagik/genie\x1B[0m"),console.log()}init_genie_config2();init_version();import{execSync as execSync3,spawn as spawn3}from"child_process";import{chmodSync as chmodSync2,closeSync as closeSync3,copyFileSync as copyFileSync3,existsSync as existsSync30,fsyncSync as fsyncSync2,mkdirSync as mkdirSync15,openSync as openSync3,readFileSync as readFileSync22,readSync as readSync2,readdirSync as readdirSync10,readlinkSync,realpathSync as realpathSync5,renameSync as renameSync6,rmSync as rmSync3,statSync as statSync8,writeFileSync as writeFileSync13}from"fs";import{homedir as homedir29}from"os";import{dirname as dirname14,join as join35}from"path";var REGISTRY=[];async function cleanupLegacyArtifacts(skipList,registry=REGISTRY){let entries=[];for(let artifact of registry){if(skipList.has(artifact.name)){entries.push({name:artifact.name,outcome:"skipped",removed:[],warnings:[]});continue}if(!await artifact.detect()){entries.push({name:artifact.name,outcome:"absent",removed:[],warnings:[]});continue}let result2=await artifact.cleanup();entries.push({name:artifact.name,outcome:"cleaned",removed:result2.removed,warnings:result2.warnings})}return{entries}}function parseSkipCleanupFlag(value){let skip=new Set;if(!value)return skip;for(let part of value.split(",")){let name=part.trim();if(name)skip.add(name)}return skip}var GENIE_HOME2=process.env.GENIE_HOME||join35(homedir29(),".genie"),GENIE_BIN=join35(GENIE_HOME2,"bin"),GENIE_BIN_STAGING=join35(GENIE_BIN,".staging"),GENIE_BIN_PREVIOUS=join35(GENIE_BIN,".previous"),TRUTHY=new Set(["1","true","yes","on"]),UPDATE_DIAGNOSTIC_SCHEMA_VERSION=3,VERIFY_PROBE_DEADLINE_MS=15000,VERIFY_PROBE_POLL_INTERVAL_MS=500,FETCH_LATEST_TIMEOUT_MS=5000,RELEASES_OWNER="automagik-dev",RELEASES_REPO="genie",RAW_BASE_URL="https://raw.githubusercontent.com";function normalizeVersion(value){let trimmed=value.trim(),plusIdx=trimmed.indexOf("+");return plusIdx===-1?trimmed:trimmed.slice(0,plusIdx)}function decideVerify(args){if(args.skipReason)return{kind:"skipped",reason:args.skipReason};if(args.serverHealthBody===null)return{kind:"health-unreachable",endpoint:args.endpoint};let rawServerVersion=args.serverHealthBody.version??null,diskVersion=rawServerVersion===null?null:normalizeVersion(rawServerVersion),pid=args.serverHealthBody.daemonPid??null;if(args.serverHealthBody.daemonInodeStale===!0)return{kind:"daemon-stale-inode",diskVersion,pid:pid??0,cwd:args.serverHealthBody.daemonCwd??""};return{kind:"ok",version:diskVersion,pid}}function shortCircuitIfCurrent(currentVersion,latestVersion){if(!latestVersion)return!1;return normalizeVersion(currentVersion)===normalizeVersion(latestVersion)}function manifestUrlForChannel(channel){let fileName=channel==="stable"?"latest.json":`${channel}.json`;return`${RAW_BASE_URL}/${RELEASES_OWNER}/${RELEASES_REPO}/main/.well-known/${fileName}`}function resolvePlatformId(){let{platform:os3,arch:cpu}=process;if(os3==="darwin"&&cpu==="arm64")return"darwin-arm64";if(os3==="linux"&&cpu==="arm64")return"linux-arm64";if(os3==="linux"&&cpu==="x64"){if(existsSync30("/etc/alpine-release"))return"linux-x64-musl";try{let out=execSync3("ldd --version 2>&1 || true",{encoding:"utf-8",timeout:1000});if(/musl/i.test(out))return"linux-x64-musl"}catch{}return"linux-x64-glibc"}throw Error(`Unsupported platform: ${os3}-${cpu}. Genie ships binaries for linux-x64-glibc, linux-x64-musl, linux-arm64, darwin-arm64.`)}function resolveLiveBinaryPath(){try{let out=execSync3("which genie",{encoding:"utf-8",timeout:1500}).trim();if(!out)return null;try{return realpathSync5(out)}catch{return out}}catch{return null}}function ensureCanonicalInstall(){let target=join35(GENIE_BIN,"genie"),live=resolveLiveBinaryPath();if(live===null)return target;let liveCanonical;try{liveCanonical=realpathSync5(live)}catch{liveCanonical=live}let targetCanonical;try{targetCanonical=existsSync30(target)?realpathSync5(target):target}catch{targetCanonical=target}if(liveCanonical===targetCanonical)return target;throw Error([`Live genie binary is at ${live}, not ${target}.`," This install pre-dates the GH-Releases cutover (wish G5). `genie update`"," only manages binaries under ~/.genie/bin/. To migrate, re-run:"," curl -fsSL https://raw.githubusercontent.com/automagik-dev/genie/main/install.sh | bash"," \u2026which downloads the latest signed tarball, installs the canonical layout,"," and points your $PATH at ~/.genie/bin/genie."].join(`
4053
+ `))}async function fetchLatestManifest(channel,opts={}){let url=manifestUrlForChannel(channel),fetcher=opts.fetcher??defaultManifestFetcher,timeoutMs=opts.timeoutMs??FETCH_LATEST_TIMEOUT_MS,raw=null;try{raw=await Promise.race([fetcher(url),new Promise((resolve6)=>setTimeout(()=>resolve6(null),timeoutMs))])}catch{return null}if(!raw)return null;try{let parsed=JSON.parse(raw);if(typeof parsed.schema_version!=="number"||typeof parsed.version!=="string"||typeof parsed.tarball_base!=="string"||!Array.isArray(parsed.platforms))return null;return{schema_version:parsed.schema_version,channel:typeof parsed.channel==="string"?parsed.channel:channel,version:parsed.version,released_at:typeof parsed.released_at==="string"?parsed.released_at:"",tarball_base:parsed.tarball_base,platforms:parsed.platforms}}catch{return null}}async function defaultManifestFetcher(url){let result2=await runCommandSilent("curl",["-fsSL","--max-time","5",url],void 0,FETCH_LATEST_TIMEOUT_MS);if(!result2.success)return null;return result2.output}async function downloadAndVerifyTarball(manifest,platform2,destDir,opts={}){let runner=opts.runner??runCommandSilent;mkdirSync15(destDir,{recursive:!0});let versionTag=`v${manifest.version}`,tarballName=`genie-${manifest.version}-${platform2}.tar.gz`,tarballPath=join35(destDir,tarballName),downloadResult=await runner("gh",["release","download",versionTag,"--repo",`${RELEASES_OWNER}/${RELEASES_REPO}`,"--dir",destDir,"--pattern",tarballName,"--pattern",`${tarballName}.bundle`,"--pattern",`${tarballName}.intoto.jsonl`,"--clobber"]);if(!downloadResult.success)throw Error(`gh release download ${versionTag} failed for ${platform2}: ${downloadResult.output.trim()||"no output"}`);if(!existsSync30(tarballPath))throw Error(`gh release download succeeded but ${tarballPath} is missing`);if(!opts.skipAttestation){let verifyResult=await runner("gh",["attestation","verify",tarballPath,"--owner",RELEASES_OWNER]);if(!verifyResult.success)throw Error(`gh attestation verify failed for ${tarballName}: ${verifyResult.output.trim()||"no output"}`)}return tarballPath}async function extractTarball(tarballPath,destDir){mkdirSync15(destDir,{recursive:!0});let result2=await runCommandSilent("tar",["-xzf",tarballPath,"-C",destDir],void 0,30000);if(!result2.success)throw Error(`tar -xzf ${tarballPath} failed: ${result2.output.trim()||"no output"}`)}function deviceIdFor(path3){let probe=existsSync30(path3)?path3:dirname14(path3);try{return statSync8(probe).dev}catch{return null}}function atomicBinarySwap(stagedBinPath,targetBinPath,previousDir,oldVersion){if(!existsSync30(stagedBinPath))throw Error(`staged binary missing: ${stagedBinPath}`);let targetDir=dirname14(targetBinPath);mkdirSync15(targetDir,{recursive:!0}),mkdirSync15(previousDir,{recursive:!0});let stagingDev=deviceIdFor(stagedBinPath),targetDev=deviceIdFor(targetBinPath),sameFs=stagingDev!==null&&targetDev!==null&&stagingDev===targetDev,oldBackup=null;if(existsSync30(targetBinPath)){if(oldBackup=join35(previousDir,`genie-${oldVersion}`),existsSync30(oldBackup))try{rmSync3(oldBackup)}catch{}renameSync6(targetBinPath,oldBackup)}if(sameFs)renameSync6(stagedBinPath,targetBinPath);else{let tmpTarget=`${targetBinPath}.tmp`;if(existsSync30(tmpTarget))try{rmSync3(tmpTarget)}catch{}copyFileSync3(stagedBinPath,tmpTarget);try{let fd=openSync3(tmpTarget,"r");try{fsyncSync2(fd)}finally{closeSync3(fd)}}catch{}renameSync6(tmpTarget,targetBinPath);try{rmSync3(stagedBinPath)}catch{}}try{chmodSync2(targetBinPath,493)}catch{}return{oldVersionBackup:oldBackup,swapped:!0,fallbackUsed:!sameFs}}function rollbackBinary(){if(!existsSync30(GENIE_BIN_PREVIOUS))throw Error(`No rollback target: ${GENIE_BIN_PREVIOUS} does not exist`);let candidates=readdirSync10(GENIE_BIN_PREVIOUS).filter((entry2)=>entry2.startsWith("genie-")).map((entry2)=>({entry:entry2,mtime:statSync8(join35(GENIE_BIN_PREVIOUS,entry2)).mtimeMs})).sort((a,b2)=>b2.mtime-a.mtime);if(candidates.length===0)throw Error(`No rollback target: ${GENIE_BIN_PREVIOUS} is empty`);let newest=candidates[0].entry,source=join35(GENIE_BIN_PREVIOUS,newest),target=join35(GENIE_BIN,"genie");mkdirSync15(GENIE_BIN,{recursive:!0});let sourceDev=deviceIdFor(source),targetDev=deviceIdFor(target),sameFs=sourceDev!==null&&targetDev!==null&&sourceDev===targetDev;if(existsSync30(target)){let replacedAt=join35(GENIE_BIN_PREVIOUS,`${newest}.replaced.${Date.now()}`);if(sameFs)renameSync6(target,replacedAt);else copyFileSync3(target,replacedAt),rmSync3(target)}if(sameFs)renameSync6(source,target);else copyFileSync3(source,target),rmSync3(source);try{chmodSync2(target,493)}catch{}return{restored:target,from:source}}var VERIFY_PROBE_ENDPOINT="pgserve status --json + ~/.genie/serve.pid";function readDaemonCwd(pid){if(process.platform!=="linux")return null;try{let cwd=readlinkSync(`/proc/${pid}/cwd`);return{cwd,staleInode:cwd.endsWith(" (deleted)")}}catch{return null}}function readInstalledPackageVersion(){let candidates=[join35(GENIE_HOME2,"VERSION"),join35(homedir29(),".bun","install","global","node_modules","@automagik","genie","package.json")],npmPrefix=safeExec("npm prefix -g",1500);if(npmPrefix)candidates.push(join35(npmPrefix,"lib","node_modules","@automagik","genie","package.json"));for(let path3 of candidates)try{let raw=readFileSync22(path3,"utf-8").trim();if(raw.startsWith("{")){let pkg=JSON.parse(raw);if(typeof pkg.version==="string"&&/^\d+\.\d+/.test(pkg.version))return pkg.version}else if(/^\d+\.\d+/.test(raw))return raw}catch{}return null}async function readServerHealth(){if(!(await runCommandSilent("pgserve",["status","--json"],void 0,3000)).success)return null;let pidPath=join35(GENIE_HOME2,"serve.pid"),rawPid=safeRead(pidPath,32);if(!rawPid)return null;let pid=Number.parseInt(rawPid.trim(),10);if(!Number.isFinite(pid)||pid<=0)return null;try{process.kill(pid,0)}catch{return null}let cwdInfo=readDaemonCwd(pid);return{version:readInstalledPackageVersion()??VERSION,daemonInodeStale:cwdInfo?.staleInode??!1,daemonPid:pid,daemonCwd:cwdInfo?.cwd}}async function pollHealth(readHealth,deadlineMs,intervalMs){let startedAt=Date.now();while(Date.now()-startedAt<deadlineMs){let body=null;try{body=await readHealth()}catch{}if(body!==null)return body;await new Promise((r)=>setTimeout(r,intervalMs))}return null}async function runVerifyProbe(opts={}){if(opts.skipReason)return decideVerify({serverHealthBody:null,endpoint:VERIFY_PROBE_ENDPOINT,skipReason:opts.skipReason});let reader=opts.readHealth??readServerHealth,deadline=opts.deadlineMs??VERIFY_PROBE_DEADLINE_MS,interval=opts.intervalMs??VERIFY_PROBE_POLL_INTERVAL_MS,body=await pollHealth(reader,deadline,interval);return decideVerify({serverHealthBody:body,endpoint:VERIFY_PROBE_ENDPOINT})}async function pm2GenieServe(){let result2=await runCommandSilent("pm2",["jlist"],void 0,3000);if(!result2.success)return null;try{let list2=JSON.parse(result2.output),candidates=pm2ProcessNameCandidates();for(let name of candidates){let entry2=list2.find((p)=>p.name===name);if(!entry2)continue;if(typeof entry2.pid!=="number"||entry2.pid<=0)continue;if(entry2.pm2_env?.status!=="online")continue;return{name,pid:entry2.pid,restartCount:entry2.pm2_env?.restart_time??0}}return null}catch{return null}}async function restartServeIfStale(){let before=await pm2GenieServe();if(!before)return null;let cwdInfo=readDaemonCwd(before.pid);if(!cwdInfo||!cwdInfo.staleInode)return null;log(`Restarting pm2 ${before.name} (stale inode detected: ${cwdInfo.cwd})`);let configPath2=null;try{configPath2=regenerateEcosystemConfig()}catch(err){let reason=err instanceof Error?err.message:String(err);error(`Could not regenerate pm2 ecosystem config (${reason}); falling back to plain restart`)}let restartArgs=configPath2?["startOrReload",configPath2,"--update-env"]:["restart",before.name,"--update-env"];if(!(await runCommandSilent("pm2",restartArgs,void 0,1e4)).success)return error(`pm2 ${restartArgs[0]} ${before.name} failed; daemon will keep serving pre-update bytes until manually restarted`),null;let deadline=Date.now()+1e4;while(Date.now()<deadline){let after=await pm2GenieServe();if(after&&(after.pid!==before.pid||after.restartCount>before.restartCount))return success(`pm2 ${after.name} restarted (pid ${before.pid} \u2192 ${after.pid})`),{oldPid:before.pid,newPid:after.pid};await new Promise((r)=>setTimeout(r,500))}return error("pm2 restart did not produce a new pid within 10s \u2014 verify probe will surface the stale state"),null}function formatVerifyBanner(result2){let lines=[];switch(result2.kind){case"ok":{let versionLabel=result2.version?`v${result2.version}`:"version unknown",pidSuffix=result2.pid?` (pid ${result2.pid}, healthy)`:" (healthy)";lines.push(`${colorize("\x1B[32m","\x1B[0m","\u2714")} Genie ${versionLabel}${pidSuffix}`);break}case"health-unreachable":lines.push(`${colorize("\x1B[31m","\x1B[0m","\u2716")} Genie server unreachable (probe: ${result2.endpoint})`),lines.push(`${colorize("\x1B[2m","\x1B[0m"," fix: pm2 restart Genie (or `genie install` if not yet supervised)")}`);break;case"daemon-stale-inode":{let versionLabel=result2.diskVersion?`v${result2.diskVersion}`:"version unknown";lines.push(`${colorize("\x1B[31m","\x1B[0m","\u2716")} Genie ${versionLabel} \u2014 daemon serving stale bytes (pid ${result2.pid})`),lines.push(`${colorize("\x1B[2m","\x1B[0m",` cwd: ${result2.cwd}`)}`),lines.push(`${colorize("\x1B[2m","\x1B[0m"," fix: pm2 restart Genie --update-env")}`);break}case"auth-invalid":lines.push(`${colorize("\x1B[31m","\x1B[0m","\u2716")} Auth: invalid`);break;case"skipped":lines.push(`${colorize("\x1B[2m","\x1B[0m",`\xB7 Genie verify skipped: ${result2.reason} (CLI in-process v${VERSION})`)}`);break}return lines}function colorEnabled(){if(process.env.NO_COLOR)return!1;if(process.env.FORCE_COLOR&&process.env.FORCE_COLOR!=="0")return!0;return Boolean(process.stdout.isTTY)}function colorize(open4,close,text){return colorEnabled()?`${open4}${text}${close}`:text}function log(message){console.log(`${colorize("\x1B[32m","\x1B[0m","\u25B8")} ${message}`)}function success(message){console.log(`${colorize("\x1B[32m","\x1B[0m","\u2714")} ${message}`)}function error(message){console.log(`${colorize("\x1B[31m","\x1B[0m","\u2716")} ${message}`)}function formatDuration2(ms){if(ms<1000)return`${ms}ms`;return`${(ms/1000).toFixed(1)}s`}function isTruthyEnv(value){return value!==void 0&&TRUTHY.has(value.trim().toLowerCase())}async function withTemporaryEnv(key,value,fn){let previous=process.env[key];process.env[key]=value;try{return await fn()}finally{if(previous===void 0)delete process.env[key];else process.env[key]=previous}}function safeExec(command,timeoutMs=1500){try{return execSync3(command,{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:timeoutMs}).trim()}catch(err){let stdout=err.stdout;if(typeof stdout==="string"&&stdout.trim())return stdout.trim();return""}}function safeRead(path3,maxChars=4000){try{let value=readFileSync22(path3,"utf-8");if(value.length<=maxChars)return value;return value.slice(value.length-maxChars)}catch{return null}}function tailLines(path3,maxBytes=64000,maxLines=200){let fd=null;try{let stat4=statSync8(path3),bytesToRead=Math.min(stat4.size,maxBytes),buffer2=Buffer.alloc(bytesToRead);return fd=openSync3(path3,"r"),readSync2(fd,buffer2,0,bytesToRead,Math.max(0,stat4.size-bytesToRead)),buffer2.toString("utf-8").split(/\r?\n/).map((line)=>line.trim()).filter(Boolean).slice(-maxLines)}catch{return[]}finally{if(fd!==null)try{closeSync3(fd)}catch{}}}function summarizeJsonlSignals(path3){let signals2=new Map;for(let line of tailLines(path3))try{let event=JSON.parse(line),level=typeof event.level==="string"?event.level:"unknown";if(level!=="error"&&level!=="warn")continue;let name=typeof event.event==="string"?event.event:"unknown",key=`${level}:${name}`,existing=signals2.get(key)??{level,event:name,count:0};if(existing.count++,typeof event.timestamp==="string")existing.lastTimestamp=event.timestamp;if(typeof event.error==="string")existing.lastError=event.error;signals2.set(key,existing)}catch{}return[...signals2.values()].sort((a,b2)=>b2.count-a.count).slice(0,10)}async function collectUpdateDiagnostics(ctx,maintenance,extras){let logsDir=join35(GENIE_HOME2,"logs");mkdirSync15(logsDir,{recursive:!0});let generatedAt=new Date().toISOString(),safeStamp=generatedAt.replace(/[:.]/g,"-"),path3=join35(logsDir,`update-diagnostics-${safeStamp}.json`),schedulerLog=join35(logsDir,"scheduler.log"),tuiCrashLog=join35(logsDir,"tui-crash.log"),signals2=summarizeJsonlSignals(schedulerLog),diagnostics={schemaVersion:UPDATE_DIAGNOSTIC_SCHEMA_VERSION,cli:"genie",generatedAt,verify:extras.verify,cleanups:extras.cleanups,update:{channel:ctx.channel,latestVersion:ctx.latestVersion,cliVersion:ctx.cliVersion,platform:ctx.platform},delivery:{manifest:ctx.manifest,tarballPath:ctx.tarballPath,attestationVerified:ctx.attestationVerified,previousBackup:ctx.previousBackup},runtime:{platform:process.platform,arch:process.arch,cwd:process.cwd(),node:process.version,bun:(await runCommandSilent("bun",["--version"])).output.trim()||null,gh:(await runCommandSilent("gh",["--version"])).output.split(`
4054
+ `)[0]?.trim()||null,genie:{which:(await runCommandSilent("which",["genie"])).output.trim()||null,tuiDisabled:isTruthyEnv(process.env.GENIE_TUI_DISABLE),updateSkipMaintenance:isTruthyEnv(process.env.GENIE_UPDATE_SKIP_MAINTENANCE)}},paths:{genieHome:GENIE_HOME2,genieBin:GENIE_BIN,genieBinStaging:GENIE_BIN_STAGING,genieBinPrevious:GENIE_BIN_PREVIOUS,logsDir,servePid:safeRead(join35(GENIE_HOME2,"serve.pid"),200),pgservePort:safeRead(join35(GENIE_HOME2,"pgserve.port"),200),schedulerLog,tuiCrashLog},processSnapshot:{genie:safeExec("ps -axo pid,ppid,pgid,stat,pcpu,pmem,etime,command -r | rg -i 'dist/genie.js|/src/genie.ts|pgserve|postgres -D .*\\.genie/data/pgserve|tmux -L genie-tui|bun' || true",2000)||null,tuiTmux:safeExec("tmux -L genie-tui ls 2>/dev/null || true",1000)||null},maintenance:{...maintenance,pgAutostartDisabled:!0,legend:{"[ok]":"healthy","[fix]":"fixed during maintenance","[--]":"skipped/non-blocking","[!!]":"operator action needed; update still completed"}},recentLogSignals:{scheduler:signals2,schedulerTail:tailLines(schedulerLog,32000,80),tuiCrashTail:tailLines(tuiCrashLog,32000,80)}};return writeFileSync13(path3,`${JSON.stringify(diagnostics,null,2)}
4055
+ `),{path:path3,signals:signals2}}async function runCommandSilent(command,args,cwd,timeoutMs=4000){return new Promise((resolve6)=>{let output=[],settled=!1,child=spawn3(command,args,{cwd,stdio:["inherit","pipe","pipe"]}),timer2=setTimeout(()=>{if(settled)return;settled=!0,child.kill("SIGTERM"),resolve6({success:!1,output:`Timed out after ${timeoutMs}ms`})},timeoutMs);child.stdout?.on("data",(data)=>{output.push(data.toString())}),child.stderr?.on("data",(data)=>{output.push(data.toString())}),child.on("close",(code)=>{if(settled)return;settled=!0,clearTimeout(timer2),resolve6({success:code===0,output:output.join("")})}),child.on("error",(err)=>{if(settled)return;settled=!0,clearTimeout(timer2),resolve6({success:!1,output:err.message})})})}var FRAMEWORK_MARKER_FILES=new Set([".orphaned_at"]);function copyDirSync(src,dest){mkdirSync15(dest,{recursive:!0});for(let entry2 of readdirSync10(src,{withFileTypes:!0})){if(FRAMEWORK_MARKER_FILES.has(entry2.name))continue;let srcPath=join35(src,entry2.name),destPath=join35(dest,entry2.name);if(entry2.isDirectory())copyDirSync(srcPath,destPath);else copyFileSync3(srcPath,destPath)}}async function resolveChannel(options){if(options.next)return"next";if(options.stable)return"stable";if(genieConfigExists())try{let config=await loadGenieConfig();if(config.updateChannel==="next")return"next";if(config.updateChannel==="latest")return"stable"}catch{}return"stable"}async function persistChannel(channel){try{let config=await loadGenieConfig();config.updateChannel=channel==="next"?"next":"latest",await saveGenieConfig(config)}catch{}}async function updateCommand(options={}){if(console.log(),console.log(`${colorize("\x1B[1m","\x1B[0m","\uD83E\uDDDE Genie CLI Update")}`),console.log(`${colorize("\x1B[2m","\x1B[0m","\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`),console.log(),options.rollback){await runRollback();return}let cleanupSkipList=buildCleanupSkipList(options),noRestart=options.restart===!1||isTruthyEnv(process.env.GENIE_UPDATE_NO_RESTART),noVerify=options.verify===!1||isTruthyEnv(process.env.GENIE_UPDATE_NO_VERIFY),channel=await resolveChannel(options);if(options.next||options.stable)await persistChannel(channel);let manifest=await fetchLatestManifest(channel),latestVersion=manifest?.version??null;if(shortCircuitIfCurrent(VERSION,latestVersion)){success(`Already up to date (v${normalizeVersion(VERSION)}, channel ${channel})`),console.log();return}let platform2;try{platform2=resolvePlatformId()}catch(err){error(err instanceof Error?err.message:String(err)),process.exit(1)}try{ensureCanonicalInstall()}catch(err){error(err instanceof Error?err.message:String(err)),process.exit(1)}if(log(`Channel: ${channel}${channel==="stable"?" (stable)":` (${channel})`}`),log(`Platform: ${platform2}`),latestVersion)log(`Update available: ${normalizeVersion(VERSION)} \u2192 ${normalizeVersion(latestVersion)}`);else log(`Channel manifest unavailable (.well-known/${channel==="stable"?"latest":channel}.json missing)`),error(`Cannot resolve target version for channel "${channel}". Aborting.`),process.exit(1);if(console.log(),!shouldAutoConfirm(options)){let proceedQuestion=`Update v${normalizeVersion(VERSION)} \u2192 v${normalizeVersion(latestVersion)}?`;if(!await promptConfirm(proceedQuestion)){console.log(),log("Update declined."),console.log();return}}let diagnosticsCtx={channel,manifest,platform:platform2,latestVersion,cliVersion:VERSION,tarballPath:null,attestationVerified:!1,previousBackup:null};try{await runDelivery(manifest,platform2,diagnosticsCtx)}catch(err){let msg=err instanceof Error?err.message:String(err);error(`Update failed: ${msg}`),process.exit(1)}let cleanupReport=await runLegacyCleanupSafe(cleanupSkipList);await runPostUpdateMaintenanceSafe({...options,noRestart,noVerify},diagnosticsCtx,cleanupReport)}async function runDelivery(manifest,platform2,diagnosticsCtx){log("Downloading signed tarball from GitHub Releases...");let tarballPath=await downloadAndVerifyTarball(manifest,platform2,GENIE_BIN_STAGING);diagnosticsCtx.tarballPath=tarballPath,diagnosticsCtx.attestationVerified=!0,success(`Verified attestation for ${tarballPath.split("/").pop()}`),log("Extracting tarball...");let extractDir=join35(GENIE_BIN_STAGING,`extract-${manifest.version}`);if(existsSync30(extractDir))rmSync3(extractDir,{recursive:!0,force:!0});await extractTarball(tarballPath,extractDir);let stagedBin=join35(extractDir,"genie");if(!existsSync30(stagedBin))throw Error(`tarball did not contain a 'genie' binary at ${stagedBin}`);try{chmodSync2(stagedBin,493)}catch{}log("Atomically swapping binary...");let targetBin=join35(GENIE_BIN,"genie"),swapResult=atomicBinarySwap(stagedBin,targetBin,GENIE_BIN_PREVIOUS,normalizeVersion(VERSION));diagnosticsCtx.previousBackup=swapResult.oldVersionBackup,success(`Genie binary updated \u2192 v${manifest.version}${swapResult.fallbackUsed?" (cross-device fallback)":""}`);try{writeFileSync13(join35(GENIE_HOME2,"VERSION"),`${manifest.version}
4056
+ `)}catch{}syncAuxiliaryContent(extractDir),cleanupStagingArtifacts(extractDir,tarballPath)}function cleanupStagingArtifacts(extractDir,tarballPath){try{rmSync3(extractDir,{recursive:!0,force:!0}),rmSync3(tarballPath);let sidecarBundle=`${tarballPath}.bundle`,sidecarIntoto=`${tarballPath}.intoto.jsonl`;if(existsSync30(sidecarBundle))rmSync3(sidecarBundle);if(existsSync30(sidecarIntoto))rmSync3(sidecarIntoto)}catch{}}function syncAuxiliaryContent(extractDir){let targets=[{src:join35(extractDir,"plugins"),dest:join35(GENIE_HOME2,"plugins"),label:"plugins"},{src:join35(extractDir,"skills"),dest:join35(GENIE_HOME2,"skills"),label:"skills"},{src:join35(extractDir,"templates"),dest:join35(GENIE_HOME2,"templates"),label:"templates"}];for(let target of targets){if(!existsSync30(target.src))continue;swapAuxiliaryTree(target.src,target.dest,target.label)}}function swapAuxiliaryTree(src,dest,label){let stagingDest=`${dest}.new`,oldDest=`${dest}.old`;try{if(existsSync30(stagingDest))rmSync3(stagingDest,{recursive:!0,force:!0});if(existsSync30(oldDest))rmSync3(oldDest,{recursive:!0,force:!0});if(copyDirSync(src,stagingDest),existsSync30(dest))renameSync6(dest,oldDest);if(renameSync6(stagingDest,dest),existsSync30(oldDest))rmSync3(oldDest,{recursive:!0,force:!0});success(`Refreshed ${label}/ \u2192 ${dest}`)}catch(err){recoverAuxiliarySwap(dest,stagingDest,oldDest);let msg=err instanceof Error?err.message:String(err);log(`Could not refresh ${label}/ (non-fatal): ${msg}`)}}function recoverAuxiliarySwap(dest,stagingDest,oldDest){try{if(!existsSync30(dest)&&existsSync30(oldDest))renameSync6(oldDest,dest);if(existsSync30(stagingDest))rmSync3(stagingDest,{recursive:!0,force:!0})}catch{}}async function runRollback(){log("Rolling back to previous binary...");try{let result2=rollbackBinary();success(`Restored ${result2.from} \u2192 ${result2.restored}`),console.log()}catch(err){let msg=err instanceof Error?err.message:String(err);error(`Rollback failed: ${msg}`),console.log(),process.exit(1)}}async function promptConfirm(question){if(!process.stdin.isTTY||!process.stdout.isTTY)return!0;return process.stdout.write(`${question} [Y/n] `),new Promise((resolve6)=>{let onData=(chunk)=>{process.stdin.removeListener("data",onData),process.stdin.pause();let answer=chunk.toString("utf-8").trim().toLowerCase();if(answer===""||answer==="y"||answer==="yes")resolve6(!0);else resolve6(!1)};process.stdin.resume(),process.stdin.once("data",onData)})}function shouldAutoConfirm(opts){if(opts.yes)return!0;return isTruthyEnv(process.env.GENIE_UPDATE_YES)}function buildCleanupSkipList(options){let skipList=parseSkipCleanupFlag(options.skipCleanup);if(options.sidecarCleanup===!1)skipList.add("nats-reply-sidecar"),log("--no-sidecar-cleanup (no-op for genie, retained for cross-CLI portability)");return skipList}async function runLegacyCleanupSafe(skipList){try{return await cleanupLegacyArtifacts(skipList)}catch(err){let msg=err instanceof Error?err.message:String(err);return log(`Legacy artifact cleanup failed (non-fatal): ${msg}`),{entries:[]}}}function printPostUpdateMaintenanceIntro(){console.log(),log("Running post-update maintenance..."),console.log(" Purpose: make first launch after update fast and collect upgrade health signals."),console.log(" Checks: runtime partitions, watchdog status, session backfill drift, zombie rows, team config orphans."),console.log(" PG policy: read-only; uses an already-running pgserve when available and will not auto-start it."),console.log(" Legend: [ok]=healthy, [fix]=fixed, [--]=skipped/non-blocking, [!!]=operator action needed.")}async function runMaintenanceWithCapturedLines(maintenanceLines){let{runPostUpdateMaintenance:runPostUpdateMaintenance2}=await Promise.resolve().then(() => (init_doctor(),exports_doctor));await withTemporaryEnv("GENIE_PG_NO_AUTOSTART","1",()=>runPostUpdateMaintenance2({log:(line)=>{maintenanceLines.push(line),console.log(line)}}))}function printDiagnosticsSummary(diagnostics){if(log("Post-update diagnostics captured."),console.log(` Report: ${diagnostics.path}`),console.log(" Include this file when opening a GitHub issue; it contains install metadata, step output,"),console.log(" local process state, and recent scheduler/TUI log signals."),diagnostics.signals.length===0)return;console.log(" Recent scheduler signals:");for(let signal of diagnostics.signals.slice(0,3)){let errorDetail=signal.lastError?` \u2014 ${signal.lastError}`:"";console.log(` ${signal.level}:${signal.event} \xD7${signal.count}${errorDetail}`)}}async function capturePostUpdateDiagnostics(diagnosticsCtx,maintenance,extras){if(!diagnosticsCtx)return;try{let diagnostics=await collectUpdateDiagnostics(diagnosticsCtx,maintenance,extras);printDiagnosticsSummary(diagnostics)}catch(err){let msg=err instanceof Error?err.message:String(err);log(`Post-update diagnostics capture failed (non-fatal): ${msg}`)}}function printVerifyBanner(result2){console.log();for(let line of formatVerifyBanner(result2))console.log(` ${line}`);console.log()}async function runPostUpdateMaintenanceSafe(options,diagnosticsCtx,cleanupReport){if(options.noRestart){log("--no-restart: skipping maintenance and verify probe.");let verify2=await runVerifyProbe({skipReason:"no-restart"});printVerifyBanner(verify2),await capturePostUpdateDiagnostics(diagnosticsCtx,{outcome:"completed",durationMs:0,lines:[]},{verify:verify2,cleanups:cleanupReport});return}if(options.skipMaintenance||isTruthyEnv(process.env.GENIE_UPDATE_SKIP_MAINTENANCE)){log("Skipping post-update maintenance (requested).");let verify2=await runVerifyProbe({skipReason:"no-restart"});printVerifyBanner(verify2),await capturePostUpdateDiagnostics(diagnosticsCtx,{outcome:"completed",durationMs:0,lines:[]},{verify:verify2,cleanups:cleanupReport});return}let startedAt=Date.now(),maintenanceLines=[],outcome="completed",maintenanceError;try{printPostUpdateMaintenanceIntro(),await runMaintenanceWithCapturedLines(maintenanceLines),success(`Post-update maintenance complete (${formatDuration2(Date.now()-startedAt)}).`)}catch(err){outcome="failed",maintenanceError=err instanceof Error?err.message:String(err),error(`Post-update maintenance skipped: ${maintenanceError}`)}await restartServeIfStaleSafe();let verify=options.noVerify?await runVerifyProbe({skipReason:"no-verify-flag"}):await runVerifyProbe();if(printVerifyBanner(verify),await capturePostUpdateDiagnostics(diagnosticsCtx,{outcome,durationMs:Date.now()-startedAt,lines:maintenanceLines,error:maintenanceError},{verify,cleanups:cleanupReport}),(verify.kind==="health-unreachable"||verify.kind==="daemon-stale-inode")&&!options.noVerify)process.exitCode=1}async function restartServeIfStaleSafe(){try{await restartServeIfStale()}catch(err){let msg=err instanceof Error?err.message:String(err);log(`Stale-serve restart skipped (non-fatal): ${msg}`)}}init_version();init_trust();init_trust();init_trust();import{execSync as execSync4}from"child_process";import{existsSync as existsSync32,mkdirSync as mkdirSync16,readFileSync as readFileSync24,renameSync as renameSync7,writeFileSync as writeFileSync14}from"fs";import{dirname as dirname15,isAbsolute,join as join37,resolve as resolve6}from"path";function resolveOriginUrl(repoRoot){try{return execSync4("git config --get remote.origin.url",{cwd:repoRoot,encoding:"utf-8"}).trim()||null}catch{return null}}function findRepoRoot(start){let current=start;while(current!=="/"){if(existsSync32(join37(current,".git")))return current;current=dirname15(current)}return null}function writeTrustFile(path3,file){let dir=dirname15(path3);if(!existsSync32(dir))mkdirSync16(dir,{recursive:!0});let sorted={version:1,entries:[...file.entries].sort((a,b2)=>a.path.localeCompare(b2.path))},serialized=`${JSON.stringify(sorted,null,2)}
4057
+ `,tmpPath=`${path3}.tmp.${process.pid}`;writeFileSync14(tmpPath,serialized,"utf-8"),renameSync7(tmpPath,path3)}function runTrustList(trustPath){let current=readTrustFile(trustPath);if(current.entries.length===0){console.log(`(trust file empty: ${trustPath})`);return}console.log(`Trusted hooks (${current.entries.length}, from ${trustPath}):`);for(let entry2 of current.entries){let scope=entry2.scope==="repo"?`repo:${entry2.repoRemoteUrl??"?"}`:entry2.scope;if(console.log(` ${entry2.path}`),console.log(` scope: ${scope}`),console.log(` sha256: ${entry2.sha256}`),console.log(` trusted: ${entry2.trustedAt}`),entry2.capabilities&&entry2.capabilities.length>0)console.log(` caps: ${entry2.capabilities.join(", ")}`);if(entry2.note)console.log(` note: ${entry2.note}`)}}function resolveTrustScope(filePath,options){if(options.repo){let repoRoot=findRepoRoot(dirname15(filePath));if(!repoRoot)console.error(`Error: --repo passed but no .git directory found above ${filePath}`),process.exit(1);let remote=resolveOriginUrl(repoRoot);if(!remote)console.error(`Error: --repo passed but ${repoRoot} has no remote.origin.url`),process.exit(1);return{scope:"repo",repoRemoteUrl:remote}}if(options.team)return{scope:"team"};return{scope:"global"}}async function confirmTrustOrAbort(yes){if(yes||!process.stdin.isTTY)return;process.stdout.write("Confirm? (y/N) ");let buf=Buffer.alloc(8),read=0;try{read=(await import("fs")).readSync(0,buf,0,buf.length,null)}catch{console.error("Error: cannot read confirmation; pass --yes to trust non-interactively"),process.exit(1)}let answer=buf.subarray(0,read).toString().trim().toLowerCase();if(answer!=="y"&&answer!=="yes")console.log("Aborted."),process.exit(1)}async function runTrustAdd(target,options,trustPath){let filePath=isAbsolute(target)?target:resolve6(process.cwd(),target);if(!existsSync32(filePath))console.error(`Error: file not found: ${filePath}`),process.exit(1);if(!filePath.endsWith(".ts"))console.error(`Error: trust target must be a .ts file: ${filePath}`),process.exit(1);let{scope,repoRemoteUrl}=resolveTrustScope(filePath,options),sha=sha256OfFile(filePath),source=readFileSync24(filePath,"utf-8"),capabilities=parseCapabilities(source);if(console.log(`About to trust: ${filePath}`),console.log(` scope: ${scope==="repo"?`repo:${repoRemoteUrl}`:scope}`),console.log(` sha256: ${sha}`),capabilities.length>0)console.log(` caps: ${capabilities.join(", ")}`);if(options.note)console.log(` note: ${options.note}`);await confirmTrustOrAbort(options.yes??!1);let current=readTrustFile(trustPath),newEntry={path:filePath,sha256:sha,scope,repoRemoteUrl,trustedAt:new Date().toISOString(),note:options.note,capabilities:capabilities.length>0?capabilities:void 0},next={version:1,entries:[...current.entries.filter((e)=>e.path!==filePath),newEntry]};writeTrustFile(trustPath,next),console.log(`Trusted ${filePath} \u2192 ${trustPath}`)}async function trustAction(target,options){let trustPath=defaultTrustPath();if(!target)return runTrustList(trustPath);await runTrustAdd(target,options,trustPath)}function registerHookTrustCommand(parent){parent.command("trust [path]").description("Add a .ts hook file to the trust allowlist (or list current entries when [path] is omitted)").option("--repo","Scope to current repo (pinned to remote.origin.url)").option("--global","Scope globally (default)").option("--team <name>","Scope to a specific team directory").option("--note <text>","Free-form note saved with the entry").option("--yes","Skip the interactive confirmation prompt").action(trustAction)}import{appendFileSync as appendFileSync3,chmodSync as chmodSync3,mkdirSync as mkdirSync17,statSync as statSync9}from"fs";import{connect as connect2}from"net";import{homedir as homedir31}from"os";import{dirname as dirname16,join as join38}from"path";var PATTERNS=[{kind:"gh-token",re:/gh[ps]_[A-Za-z0-9]{30,}/g},{kind:"sk-token",re:/sk-[A-Za-z0-9-]{20,}/g},{kind:"glpat",re:/glpat-[A-Za-z0-9_-]{20,}/g},{kind:"hex",re:/\b[a-f0-9]{40,}\b/g}];function redactTokenShapes(text){if(text==null)return null;if(process.env.GENIE_HOOK_REDACTION==="off")return String(text);let out=String(text);for(let{kind,re}of PATTERNS)out=out.replace(re,`[REDACTED:${kind}]`);return out}function defaultSocketPath(){if(process.env.GENIE_HOOK_SOCK)return process.env.GENIE_HOOK_SOCK;let home=process.env.GENIE_HOME??join38(homedir31(),".genie");return join38(home,"hook.sock")}function fallbackLogPath2(){let home=process.env.GENIE_HOME??join38(homedir31(),".genie");return join38(home,"hook-fallback.log")}var MAX_FRAME_BYTES=1048576,FALLBACK_LOG_MAX_BYTES=104857600,DEFAULT_TIMEOUT_MS=5000;function readStdinSync(){let chunks=[],total=0,fd=0,buf=Buffer.alloc(65536);while(!0){let n;try{n=__require("fs").readSync(fd,buf,0,buf.length,null)}catch{break}if(n===0)break;if(chunks.push(Buffer.from(buf.subarray(0,n))),total+=n,total>MAX_FRAME_BYTES)break}return Buffer.concat(chunks,Math.min(total,MAX_FRAME_BYTES))}function summarizePayload(payload){try{let obj=JSON.parse(payload.toString("utf-8")),event=typeof obj.hook_event_name==="string"?obj.hook_event_name:null,tool=typeof obj.tool_name==="string"?obj.tool_name:null,command=null,ti=obj.tool_input;if(ti&&typeof ti.command==="string")command=ti.command.split(`
4055
4058
  `)[0].slice(0,256);return{event,tool,command}}catch{return{event:null,tool:null,command:null}}}function ensureLogPermissions(path3){let st;try{st=statSync9(path3)}catch{return}let mode=st.mode&511;if(mode===384)return;try{chmodSync3(path3,384),process.stderr.write(`[genie-hook] tightened ${path3} permissions ${mode.toString(8)} -> 600
4056
- `)}catch{}}function appendFallback(record){let path3=fallbackLogPath2();try{mkdirSync17(dirname15(path3),{recursive:!0}),ensureLogPermissions(path3);let safe={...record,command:redactTokenShapes(record.command)},writeFresh=!1;try{if(statSync9(path3).size>=FALLBACK_LOG_MAX_BYTES)writeFresh=!0}catch{}let line=`${JSON.stringify(safe)}
4059
+ `)}catch{}}function appendFallback(record){let path3=fallbackLogPath2();try{mkdirSync17(dirname16(path3),{recursive:!0}),ensureLogPermissions(path3);let safe={...record,command:redactTokenShapes(record.command)},writeFresh=!1;try{if(statSync9(path3).size>=FALLBACK_LOG_MAX_BYTES)writeFresh=!0}catch{}let line=`${JSON.stringify(safe)}
4057
4060
  `;if(writeFresh)__require("fs").writeFileSync(path3,line,{mode:384});else appendFileSync3(path3,line,{mode:384})}catch{}}function buildFrame(payload){let header=Buffer.alloc(4);return header.writeUInt32BE(payload.length,0),Buffer.concat([header,payload])}function parseStep(acc,length){if(length===-1){if(acc.length<4)return{kind:"incomplete",length:-1};let declared=acc.readUInt32BE(0);if(declared>MAX_FRAME_BYTES)return{kind:"error",reason:`oversized frame ${declared}`};if(declared===0)return{kind:"done",body:Buffer.alloc(0)};if(acc.length>=4+declared)return{kind:"done",body:acc.subarray(4,4+declared)};return{kind:"incomplete",length:declared}}if(acc.length>=4+length)return{kind:"done",body:acc.subarray(4,4+length)};return{kind:"incomplete",length}}async function roundtrip(socketPath,payload,timeoutMs){return new Promise((resolve7)=>{let settled=!1,finish=(result2)=>{if(settled)return;settled=!0,resolve7(result2)},timer2=setTimeout(()=>{try{sock.destroy()}catch{}finish({reply:null,reason:`timeout after ${timeoutMs}ms`})},timeoutMs);timer2.unref();let sock=connect2(socketPath);sock.once("connect",()=>{sock.write(buildFrame(payload))});let acc=Buffer.alloc(0),length=-1;sock.on("data",(chunk)=>{acc=acc.length===0?Buffer.from(chunk):Buffer.concat([acc,Buffer.from(chunk)],acc.length+chunk.length);let step=parseStep(acc,length);if(step.kind==="incomplete"){length=step.length;return}clearTimeout(timer2);try{sock.destroy()}catch{}if(step.kind==="done")finish({reply:step.body.toString("utf-8")});else finish({reply:null,reason:step.reason})}),sock.once("error",(err)=>{clearTimeout(timer2);let code=err.code??"unknown";finish({reply:null,reason:`connect error: ${code}`})}),sock.once("end",()=>{if(!settled)clearTimeout(timer2),finish({reply:null,reason:"socket closed before reply"})})})}async function runDispatchClient(){let payload=readStdinSync();if(payload.length===0)return 0;let socketPath=process.env.GENIE_HOOK_SOCK??defaultSocketPath(),timeoutMs=Number.parseInt(process.env.GENIE_HOOK_TIMEOUT_MS??"",10),effectiveTimeout=Number.isFinite(timeoutMs)&&timeoutMs>0?timeoutMs:DEFAULT_TIMEOUT_MS,result2=await roundtrip(socketPath,payload,effectiveTimeout);if(result2.reply!==null){if(result2.reply.length>0)process.stdout.write(result2.reply);return 0}let summary=summarizePayload(payload),agentId=process.env.GENIE_AGENT_ID??process.env.GENIE_AGENT_NAME??null;return appendFallback({ts:new Date().toISOString(),event:summary.event,tool:summary.tool,command:summary.command,agent_id:agentId,reason:result2.reason??"unknown"}),0}init_hooks();async function readStdin(){let chunks=[];for await(let chunk of Bun.stdin.stream())chunks.push(Buffer.from(chunk));return Buffer.concat(chunks).toString("utf-8")}async function dispatchAction(){if(process.env.GENIE_SKIP_DB_BOOT="1",process.env.GENIE_HOOK_FORCE_INPROC!=="1"){let code=await runDispatchClient();await drainStdout(),process.exit(code)}let stdin=await readStdin();if(!stdin.trim())process.exit(0);let result2=await dispatch(stdin);if(result2)process.stdout.write(result2);await drainStdout(),process.exit(0)}function drainStdout(){return new Promise((resolve8)=>{process.stdout.write("",()=>resolve8())})}function registerHookNamespace(program2){let hook=program2.command("hook").description("Hook middleware for Claude Code integration");hook.command("dispatch").description("Dispatch a CC hook event (reads JSON from stdin, writes decision to stdout)").action(dispatchAction),registerHookTrustCommand(hook)}init_audit();init_db();init_interactivity();init_otel_receiver();init_target_resolver();init_tmux();init_orchestrator();async function resolveOrcTarget(target){let resolved=await resolveTarget(target);return{paneId:resolved.paneId,session:resolved.session||target,label:formatResolvedLabel(resolved,target)}}async function sendTextChoice(paneId,text){await executeTmux2(`send-keys -t '${paneId}' End`),await sleep2(100),await executeTmux2(`send-keys -t '${paneId}' Enter`),await sleep2(100),await executeTmux2(`send-keys -t '${paneId}' ${shellEscape(text)}`),await sleep2(100),await executeTmux2(`send-keys -t '${paneId}' Enter`)}function findCurrentOption(output){let lines=stripAnsi(output).split(`
4058
4061
  `);for(let line of lines){let match=line.match(/^\s*\u276F\s*(\d+)\./);if(match)return Number.parseInt(match[1],10)}return 1}async function navigateToOption(paneId,targetOption,currentOption){let diff=targetOption-currentOption,key=diff>0?"Down":"Up";for(let i2=0;i2<Math.abs(diff);i2++)await executeTmux2(`send-keys -t '${paneId}' ${key}`),await sleep2(50);await sleep2(100),await executeTmux2(`send-keys -t '${paneId}' Enter`)}async function answerQuestion(target,choice){try{let{paneId,label}=await resolveOrcTarget(target),output=await capturePaneContent(paneId,50),state=detectState(output);if(state.type!=="question"){console.log(`No question pending (state: ${state.type})`);return}if(choice.startsWith("text:")){let text=choice.slice(5);await sendTextChoice(paneId,text),console.log(`Sent feedback: "${text.substring(0,50)}${text.length>50?"...":""}"`)}else if(/^\d+$/.test(choice)){let targetOption=Number.parseInt(choice,10);await navigateToOption(paneId,targetOption,findCurrentOption(output)),console.log(`Selected option ${targetOption} for ${label}`)}else await executeTmux2(`send-keys -t '${paneId}' '${choice}'`),console.log(`Sent '${choice}' to ${label}`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function shellEscape(str2){return`"${str2.replace(/"/g,"\\\"").replace(/\$/g,"\\$")}"`}function sleep2(ms){return new Promise((resolve8)=>setTimeout(resolve8,ms))}function registerAgentAnswer(parent){parent.command("answer <name> <choice>").description('Answer a question for an agent (use "text:..." for text input)').action(async(name,choice)=>{try{await answerQuestion(name,choice)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}var _brief;async function getBrief(){if(!_brief)_brief=await Promise.resolve().then(() => (init_brief(),exports_brief));return _brief}async function handleBrief(options){let team=options.team??process.env.GENIE_TEAM;if(!team)console.error("Error: --team is required (or set GENIE_TEAM)"),process.exit(1);let agent=options.agent??process.env.GENIE_AGENT_NAME,briefService=await getBrief(),brief=await briefService.generateBrief({team,agent,since:options.since,repoPath:process.cwd()});console.log(briefService.formatBrief(brief))}function registerAgentBrief(parent){parent.command("brief").description("Show startup brief \u2014 aggregated context since last session").option("--team <name>","Team name (default: GENIE_TEAM)").option("--agent <name>","Agent name (default: GENIE_AGENT_NAME)").option("--since <iso>","Start timestamp (default: last executor end)").action(async(options)=>{try{await handleBrief(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_agent_directory();init_agent_sync();init_builtin_agents();init_genie_config2();async function showEntry(name,json2){let resolved=await resolve7(name);if(!resolved)console.error(`Agent "${name}" not found in directory or built-ins.`),process.exit(1);if(json2){console.log(JSON.stringify({...resolved.entry,builtin:resolved.builtin},null,2));return}if(resolved.builtin)console.log(`
4059
4062
  (built-in agent)`);if(console.log(""),console.log(` Name: ${resolved.entry.name}`),console.log(` Dir: ${contractPath(resolved.entry.dir)}`),resolved.entry.repo)console.log(` Repo: ${contractPath(resolved.entry.repo)}`);if(console.log(` Prompt mode: ${resolved.entry.promptMode}`),resolved.entry.model)console.log(` Model: ${resolved.entry.model}`);if(resolved.entry.roles?.length)console.log(` Roles: ${resolved.entry.roles.join(", ")}`);console.log(` Registered: ${resolved.entry.registeredAt}`),console.log("")}function printRegisteredAgentsTable(entries){let termW=process.stdout.columns||120,repoValues=entries.map((e)=>e.repo?contractPath(e.repo):contractPath(e.dir)),maxRepoLen=Math.max(4,...repoValues.map((v)=>v.length)),fixedW=42,repoW=Math.min(maxRepoLen+2,Math.max(30,termW-42-20));console.log(""),console.log("REGISTERED AGENTS"),console.log("-".repeat(Math.max(90,42+repoW+20))),console.log(` ${"NAME".padEnd(22)}${"SCOPE".padEnd(10)}${"REPO".padEnd(repoW)}${"MODEL".padEnd(8)}ROLES`);for(let i2=0;i2<entries.length;i2++){let entry2=entries[i2],repo=repoValues[i2],roles=entry2.roles?.join(", ")||"-";console.log(` ${entry2.name.padEnd(22)}${entry2.scope.padEnd(10)}${repo.padEnd(repoW)}${(entry2.model||"-").padEnd(8)}${roles}`)}console.log("")}function printBuiltinAgentsTable(){console.log("BUILT-IN AGENTS"),console.log("-".repeat(80)),console.log(` ${"NAME".padEnd(22)}${"TYPE".padEnd(10)}${"MODEL".padEnd(8)}DESCRIPTION`);for(let agent of ALL_BUILTINS)console.log(` ${agent.name.padEnd(22)}${agent.category.padEnd(10)}${(agent.model||"-").padEnd(8)}${agent.description}`);console.log("")}async function listEntries(json2,includeBuiltins,_includeArchived){let entries=await ls();if(json2){let result2=entries.map((e)=>({...e,builtin:!1}));if(includeBuiltins)for(let b2 of ALL_BUILTINS)result2.push({name:b2.name,description:b2.description,model:b2.model,category:b2.category,scope:"built-in",builtin:!0});console.log(JSON.stringify(result2,null,2));return}if(entries.length===0&&!includeBuiltins){console.log(`
@@ -4140,7 +4143,7 @@ Registering in Omni (${omniUrl})...`);let existingId=await findOmniAgent(name);i
4140
4143
  /genie:omni
4141
4144
 
4142
4145
  `);return}await handleOmniRegistration(name,{...options,roles})}function registerAgentRegister(parent){parent.command("register <name>").description("Register an agent locally and auto-register in Omni when configured").requiredOption("--dir <path>","Agent folder (CWD + AGENTS.md)").option("--repo <path>","Default git repo (overridden by team)").option("--prompt-mode <mode>","Prompt mode: append or system","append").option("--model <model>","Default model (sonnet, opus, codex)").option("--roles <roles...>","Built-in roles this agent can orchestrate").option("--global","Write to global directory instead of project").option("--skip-omni","Skip Omni auto-registration (prints a stderr warning explaining the cost)").option("--allow-symlink","Accept a symlinked AGENTS.md (default: rejected \u2014 usually indicates --dir was pointed at the wrong folder)").action(async(name,options)=>{try{await handleAgentRegister(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_agents();function registerAgentResume(parent){parent.command("resume [name]").description("Resume a suspended/failed agent with its Claude session").option("--all","Resume all eligible agents").option("--no-reset-attempts","Preserve resumeAttempts counter (scheduler auto-resume use)").action(async(name,options)=>{try{await handleWorkerResume(name,{all:options.all,noResetAttempts:options.resetAttempts===!1})}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_msg();function registerAgentSend(parent){parent.command("send <body>").description("Send a direct message to an agent (hierarchy-enforced)").option("--to <agent>","Recipient agent name (default: team leader)","team-lead").option("--from <sender>","Sender ID (auto-detected from context)").option("--team <name>","Explicit team context for sender/recipient resolution").option("--broadcast","Send to all direct reports").action(async(body,options)=>{try{let from=options.from??await detectSenderIdentity(options.team);if(options.broadcast){await handleBroadcast2(from,body,options.team);return}await handleDirectMessage(from,options.to,body,options.team)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}async function isTeamLeader(agentName,teamName){try{let{resolveLeaderName:resolveLeaderName2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),leaderName=await resolveLeaderName2(teamName);return agentName===leaderName}catch{return!1}}async function checkHierarchy(from,to){if(isCliSender(from))return{allowed:!0};if(from===to)return{allowed:!0};try{let registry=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),team=process.env.GENIE_TEAM,[senderId,recipientId]=await Promise.all([registry.resolveAgentId(from,team),registry.resolveAgentId(to,team)]),sender=senderId?await registry.getAgent(senderId):null,recipient=recipientId?await registry.getAgent(recipientId):null;if(!sender||!recipient)return{allowed:!0};if(recipient.reportsTo===from||recipient.reportsTo===sender.id)return{allowed:!0};if(sender.reportsTo===to||sender.reportsTo===recipient.id)return{allowed:!0};if(sender.reportsTo&&sender.reportsTo===recipient.reportsTo)return{allowed:!0};if(sender.team&&sender.team===recipient.team&&await isTeamLeader(from,sender.team))return{allowed:!0};if(!sender.reportsTo&&sender.team&&sender.team===recipient.team)return{allowed:!0};let manager=sender.reportsTo??"your manager";return{allowed:!1,reason:`Cannot reach "${to}". Escalate to ${manager}.`}}catch{return{allowed:!0}}}async function handleDirectMessage(from,to,body,team){let{allowed,reason}=await checkHierarchy(from,to);if(!allowed)console.error(`Error: ${reason}`),process.exit(1);let{checkSendScope:checkSendScope2}=await Promise.resolve().then(() => (init_msg(),exports_msg)),repoPath=process.cwd(),scopeError=await checkSendScope2(repoPath,from,to);if(scopeError)console.error(`Error: ${scopeError}`),process.exit(1);let taskService=await Promise.resolve().then(() => (init_task_service(),exports_task_service)),mailbox=await Promise.resolve().then(() => (init_mailbox(),exports_mailbox)),registry=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),teamScope=team??process.env.GENIE_TEAM,toAgentId=await registry.resolveAgentIdStrict(to,teamScope),senderActor={actorType:"local",actorId:from},recipientActor={actorType:"local",actorId:toAgentId},conv=await taskService.findOrCreateConversation({type:"dm",members:[senderActor,recipientActor],createdBy:senderActor});await taskService.addMember(conv.id,senderActor),await taskService.addMember(conv.id,recipientActor),await mailbox.send(repoPath,from,toAgentId,body);let msg=await taskService.sendMessage(conv.id,senderActor,body);try{let{publishSubjectEvent:publishSubjectEvent2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events));await publishSubjectEvent2(repoPath,`genie.msg.${to}`,{kind:"message",agent:from,direction:"out",peer:to,text:body,data:{messageId:msg.id,conversationId:conv.id,from,to},source:"mailbox"})}catch{}try{let nativeTeams=await Promise.resolve().then(() => (init_claude_native_teams(),exports_claude_native_teams)),nativeMsg={from,text:body,summary:body.length>50?`${body.substring(0,50)}...`:body,timestamp:new Date().toISOString(),color:"blue",read:!1},currentTeam=team??process.env.GENIE_TEAM;if(currentTeam){let nativeName=await nativeTeams.resolveNativeMemberName(currentTeam,to);if(nativeName)await nativeTeams.writeNativeInbox(currentTeam,nativeName,nativeMsg)}}catch{}console.log(`Message sent to "${to}".`),console.log(` ID: ${msg.id}`),console.log(` Conversation: ${conv.id}`)}async function deliverBroadcastToMembers(deps,repoPath,from,teamName,body){let members=await deps.listMembers(teamName)??[],results=[];for(let member of members){if(member===from)continue;try{let r=await deps.sendMessage(repoPath,from,member,body,teamName);results.push({member,delivered:r.delivered,reason:r.reason})}catch(err){results.push({member,delivered:!1,reason:err instanceof Error?err.message:String(err)})}}return results}async function handleBroadcast2(from,body,team){let taskService=await Promise.resolve().then(() => (init_task_service(),exports_task_service)),repoPath=process.cwd(),teamName=team??process.env.GENIE_TEAM;if(!teamName)console.error("Error: Could not detect team. Use --team <name>."),process.exit(1);let senderActor={actorType:"local",actorId:from},conv=await taskService.findOrCreateConversation({type:"group",name:`Team: ${teamName}`,linkedEntity:"team",linkedEntityId:teamName,createdBy:senderActor,members:[senderActor]});await taskService.addMember(conv.id,senderActor);let msg=await taskService.sendMessage(conv.id,senderActor,body);try{let{publishSubjectEvent:publishSubjectEvent2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events));await publishSubjectEvent2(repoPath,"genie.msg.broadcast",{kind:"message",agent:from,direction:"out",peer:teamName,text:body,data:{messageId:msg.id,conversationId:conv.id,from,team:teamName},source:"mailbox"})}catch{}let{listMembers:listMembers2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),protocolRouter=await Promise.resolve().then(() => (init_protocol_router(),exports_protocol_router)),fanoutResults=await deliverBroadcastToMembers({listMembers:listMembers2,sendMessage:protocolRouter.sendMessage},repoPath,from,teamName,body);console.log(`Broadcast sent to team "${teamName}".`),console.log(` Message ID: ${msg.id}`),console.log(` Conversation: ${conv.id}`);let deliveredCount=fanoutResults.filter((r)=>r.delivered).length;console.log(` Fan-out: ${deliveredCount}/${fanoutResults.length} members reached`);for(let r of fanoutResults)if(!r.delivered)console.log(` \u26A0 ${r.member}: ${r.reason??"delivery failed"}`)}init_term_format();function printAgentFields(agent){if(console.log(""),console.log(`AGENT: ${agent.customName??agent.role??agent.id}`),console.log("\u2500".repeat(60)),console.log(` ${padRight("ID:",20)} ${agent.id}`),agent.role)console.log(` ${padRight("Role:",20)} ${agent.role}`);if(agent.customName)console.log(` ${padRight("Name:",20)} ${agent.customName}`);if(agent.team)console.log(` ${padRight("Team:",20)} ${agent.team}`);console.log(` ${padRight("Started:",20)} ${agent.startedAt}`)}function printExecutorFields(executor){if(console.log(""),console.log("Current Executor:"),console.log("\u2500".repeat(60)),console.log(` ${padRight("Executor ID:",20)} ${executor.id}`),console.log(` ${padRight("Provider:",20)} ${executor.provider}`),console.log(` ${padRight("Transport:",20)} ${executor.transport}`),console.log(` ${padRight("State:",20)} ${executor.state}`),executor.pid)console.log(` ${padRight("PID:",20)} ${executor.pid}`);if(executor.tmuxSession)console.log(` ${padRight("Tmux Session:",20)} ${executor.tmuxSession}`);if(executor.tmuxPaneId)console.log(` ${padRight("Tmux Pane:",20)} ${executor.tmuxPaneId}`);if(executor.worktree)console.log(` ${padRight("Worktree:",20)} ${executor.worktree}`);if(console.log(` ${padRight("Started:",20)} ${executor.startedAt}`),executor.endedAt)console.log(` ${padRight("Ended:",20)} ${executor.endedAt}`)}async function showAgent(name,json2){let registry=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),executorRegistry=await Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),team=process.env.GENIE_TEAM,id=await registry.resolveAgentId(name,team),agent=id?await registry.getAgent(id):null;if(!agent)console.error(`Agent "${name}" not found.`),process.exit(1);if(json2){let executor=agent.currentExecutorId?await executorRegistry.getExecutor(agent.currentExecutorId):null;console.log(JSON.stringify({agent,executor},null,2));return}if(printAgentFields(agent),agent.currentExecutorId){let executor=await executorRegistry.getExecutor(agent.currentExecutorId);if(executor)printExecutorFields(executor)}else console.log(`
4143
- No active executor.`);console.log("")}function registerAgentShow(parent){parent.command("show <name>").description("Show agent identity and current executor detail").option("--json","Output as JSON").action(async(name,options)=>{try{await showAgent(name,options.json)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_provider_models();init_agents();function parseNumericFlag(flagName){return(value)=>{let n=Number(value);if(Number.isNaN(n))throw Error(`${flagName} must be a number, got: ${value}`);return n}}function registerAgentSpawn(parent){parent.command("spawn <name>").description("Spawn a new agent by name (resolves from directory or built-ins)").option("--provider <provider>","Provider: claude, codex, or claude-sdk").option("--team <team>","Team name").option("--model <model>","Model override (e.g., sonnet, opus)").option("--skill <skill>","Skill to load (optional)").option("--layout <layout>","Layout mode: mosaic (default) or vertical").option("--color <color>","Teammate pane border color").option("--plan-mode","Start teammate in plan mode").option("--permission-mode <mode>","Permission mode (e.g., acceptEdits)").option("--extra-args <args...>","Extra CLI args forwarded to provider").option("--cwd <path>","Working directory for the agent (overrides directory entry)").option("--session <session>","Tmux session name to spawn into").option("--role <role>","Override role name for registration (avoids duplicate guard)").option("--new-window","Create a new tmux window instead of splitting").option("--window <target>","Tmux window to split into (e.g., genie:3)").option("--no-auto-resume","Disable auto-resume on pane death").option("--no-auto-sync","Disable auto-registration from workspace agents directory").option("--prompt <prompt>","Initial prompt (first user message)").option("--sdk-max-turns <n>","SDK: max conversation turns",parseNumericFlag("--sdk-max-turns")).option("--sdk-max-budget <usd>","SDK: max budget in USD",parseNumericFlag("--sdk-max-budget")).option("--sdk-stream","SDK: enable streaming output (shortcut for --stream)").option("--sdk-effort <level>","SDK: reasoning effort level (low, medium, high, max)").option("--sdk-resume <session-id>","SDK: resume a previous session by ID").action(async(name,options)=>{if(options.prompt)options.initialPrompt=options.prompt;if(options.autoSync===!1)options.noAutoSync=!0;try{validateProviderModel({provider:options.provider??null,model:options.model??null})}catch(error2){if(error2 instanceof CrossProviderModelError)console.error(`Error: ${error2.message}`),process.exit(1);throw error2}try{await handleWorkerSpawn(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_agents();function registerAgentStop(parent){parent.command("stop <name>").description("Stop an agent (preserves session for resume)").action(async(name)=>{try{await handleWorkerStop(name)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}function registerAgentCommands(program2){let agent=program2.command("agent").description("Agent lifecycle management");registerAgentSpawn(agent),registerAgentStop(agent),registerAgentResume(agent),registerAgentRecover(agent),registerAgentKill(agent),registerAgentList(agent),registerAgentShow(agent),registerAgentObserve(agent),registerAgentAnswer(agent),registerAgentRegister(agent),registerAgentDirectory(agent),registerAgentInbox(agent),registerAgentBrief(agent),registerAgentLog(agent),registerAgentSend(agent),agent.on("command:*",(operands)=>{let cmd=operands[0],available=agent.commands.map((c)=>c.name()).join(", ");agent.error(`Unknown agent command '${cmd}'. Available: ${available}`)})}init_agents();async function handleTuiMode(){let{isServeRunning:isServeRunning2,autoStartServe:autoStartServe2}=await Promise.resolve().then(() => (init_serve(),exports_serve));if(!isServeRunning2())console.log("Starting genie serve..."),await autoStartServe2();let{attachTuiSession:attachTuiSession2}=await Promise.resolve().then(() => (init_tmux2(),exports_tmux2));attachTuiSession2()}async function findTauriBinary(){let{existsSync:existsSync54}=await import("fs"),{join:join66,dirname:dirname23}=await import("path"),{execSync:execSync11}=await import("child_process"),appName="genie-desktop",rootDir=join66(dirname23(new URL(import.meta.url).pathname),"..",".."),localBin=[join66(rootDir,"packages","genie-app","src-tauri","target","release","genie-desktop"),join66(rootDir,"packages","genie-app","src-tauri","target","debug","genie-desktop"),join66(rootDir,"dist","app","genie-desktop"),"/usr/local/bin/genie-desktop"].find((p)=>existsSync54(p));if(localBin)return localBin;try{return execSync11("which genie-desktop",{stdio:"ignore"}),"genie-desktop"}catch{return}}function registerAppCommand(program2){program2.command("app").description("Launch Genie desktop app (backend sidecar + views)").option("--backend-only","Start only the backend sidecar (IPC on stdin/stdout)").option("--tui","Fall back to terminal UI mode").option("--dev","Development mode").action(async(options)=>{if(options.tui){await handleTuiMode();return}if(options.backendOnly){await Promise.resolve().then(() => (init_src_backend(),exports_src_backend));return}let tauriBin=await findTauriBinary();if(tauriBin){console.log("\x1B[35m\u25C6 Genie App\x1B[0m Launching desktop...");let{execFileSync:execFileSync3}=await import("child_process");try{execFileSync3(tauriBin,[],{stdio:"inherit"})}catch{}return}console.log("\x1B[35m\u25C6 Genie App\x1B[0m Starting backend sidecar..."),console.log("\x1B[2mDesktop binary not found \u2014 running in sidecar mode.\x1B[0m"),console.log("\x1B[2mPG bridge + PTY manager + IPC on stdin/stdout\x1B[0m"),console.log(`\x1B[2mUse --tui for terminal UI, or pipe to a frontend shell.\x1B[0m
4146
+ No active executor.`);console.log("")}function registerAgentShow(parent){parent.command("show <name>").description("Show agent identity and current executor detail").option("--json","Output as JSON").action(async(name,options)=>{try{await showAgent(name,options.json)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_provider_models();init_agents();function parseNumericFlag(flagName){return(value)=>{let n=Number(value);if(Number.isNaN(n))throw Error(`${flagName} must be a number, got: ${value}`);return n}}function registerAgentSpawn(parent){parent.command("spawn <name>").description("Spawn a new agent by name (resolves from directory or built-ins)").option("--provider <provider>","Provider: claude, codex, or claude-sdk").option("--team <team>","Team name").option("--model <model>","Model override (e.g., sonnet, opus)").option("--skill <skill>","Skill to load (optional)").option("--layout <layout>","Layout mode: mosaic (default) or vertical").option("--color <color>","Teammate pane border color").option("--plan-mode","Start teammate in plan mode").option("--permission-mode <mode>","Permission mode (e.g., acceptEdits)").option("--extra-args <args...>","Extra CLI args forwarded to provider").option("--cwd <path>","Working directory for the agent (overrides directory entry)").option("--session <session>","Tmux session name to spawn into").option("--role <role>","Override role name for registration (avoids duplicate guard)").option("--new-window","Create a new tmux window instead of splitting").option("--window <target>","Tmux window to split into (e.g., genie:3)").option("--no-auto-resume","Disable auto-resume on pane death").option("--no-auto-sync","Disable auto-registration from workspace agents directory").option("--prompt <prompt>","Initial prompt (first user message)").option("--sdk-max-turns <n>","SDK: max conversation turns",parseNumericFlag("--sdk-max-turns")).option("--sdk-max-budget <usd>","SDK: max budget in USD",parseNumericFlag("--sdk-max-budget")).option("--sdk-stream","SDK: enable streaming output (shortcut for --stream)").option("--sdk-effort <level>","SDK: reasoning effort level (low, medium, high, max)").option("--sdk-resume <session-id>","SDK: resume a previous session by ID").action(async(name,options)=>{if(options.prompt)options.initialPrompt=options.prompt;if(options.autoSync===!1)options.noAutoSync=!0;try{validateProviderModel({provider:options.provider??null,model:options.model??null})}catch(error2){if(error2 instanceof CrossProviderModelError)console.error(`Error: ${error2.message}`),process.exit(1);throw error2}try{await handleWorkerSpawn(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_agents();function registerAgentStop(parent){parent.command("stop <name>").description("Stop an agent (preserves session for resume)").action(async(name)=>{try{await handleWorkerStop(name)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}function registerAgentCommands(program2){let agent=program2.command("agent").description("Agent lifecycle management");registerAgentSpawn(agent),registerAgentStop(agent),registerAgentResume(agent),registerAgentRecover(agent),registerAgentKill(agent),registerAgentList(agent),registerAgentShow(agent),registerAgentObserve(agent),registerAgentAnswer(agent),registerAgentRegister(agent),registerAgentDirectory(agent),registerAgentInbox(agent),registerAgentBrief(agent),registerAgentLog(agent),registerAgentSend(agent),agent.on("command:*",(operands)=>{let cmd=operands[0],available=agent.commands.map((c)=>c.name()).join(", ");agent.error(`Unknown agent command '${cmd}'. Available: ${available}`)})}init_agents();async function handleTuiMode(){let{isServeRunning:isServeRunning2,autoStartServe:autoStartServe2}=await Promise.resolve().then(() => (init_serve(),exports_serve));if(!isServeRunning2())console.log("Starting genie serve..."),await autoStartServe2();let{attachTuiSession:attachTuiSession2}=await Promise.resolve().then(() => (init_tmux2(),exports_tmux2));attachTuiSession2()}async function findTauriBinary(){let{existsSync:existsSync54}=await import("fs"),{join:join66,dirname:dirname24}=await import("path"),{execSync:execSync11}=await import("child_process"),appName="genie-desktop",rootDir=join66(dirname24(new URL(import.meta.url).pathname),"..",".."),localBin=[join66(rootDir,"packages","genie-app","src-tauri","target","release","genie-desktop"),join66(rootDir,"packages","genie-app","src-tauri","target","debug","genie-desktop"),join66(rootDir,"dist","app","genie-desktop"),"/usr/local/bin/genie-desktop"].find((p)=>existsSync54(p));if(localBin)return localBin;try{return execSync11("which genie-desktop",{stdio:"ignore"}),"genie-desktop"}catch{return}}function registerAppCommand(program2){program2.command("app").description("Launch Genie desktop app (backend sidecar + views)").option("--backend-only","Start only the backend sidecar (IPC on stdin/stdout)").option("--tui","Fall back to terminal UI mode").option("--dev","Development mode").action(async(options)=>{if(options.tui){await handleTuiMode();return}if(options.backendOnly){await Promise.resolve().then(() => (init_src_backend(),exports_src_backend));return}let tauriBin=await findTauriBinary();if(tauriBin){console.log("\x1B[35m\u25C6 Genie App\x1B[0m Launching desktop...");let{execFileSync:execFileSync3}=await import("child_process");try{execFileSync3(tauriBin,[],{stdio:"inherit"})}catch{}return}console.log("\x1B[35m\u25C6 Genie App\x1B[0m Starting backend sidecar..."),console.log("\x1B[2mDesktop binary not found \u2014 running in sidecar mode.\x1B[0m"),console.log("\x1B[2mPG bridge + PTY manager + IPC on stdin/stdout\x1B[0m"),console.log(`\x1B[2mUse --tui for terminal UI, or pipe to a frontend shell.\x1B[0m
4144
4147
  `),await Promise.resolve().then(() => (init_src_backend(),exports_src_backend))})}init_claude_sdk_remote_approval();init_workspace();async function handleRequest(options){let ws=findWorkspace(),permissions=ws?getWorkspaceConfig(ws.root).permissions:void 0,timeoutSec=options.timeout?Number(options.timeout):permissions?.timeout??300,defaultAction=permissions?.defaultAction??"deny",timeoutAt=new Date(Date.now()+timeoutSec*1000),approvalId=await insertApproval(`cli-${process.pid}`,options.agent,options.tool,options.input,timeoutAt);if(console.log(`Approval created: ${approvalId}`),options.wait){console.log(`Waiting for resolution (timeout: ${timeoutSec}s, default: ${defaultAction})...`);let decision=await waitForResolution(approvalId,timeoutAt,defaultAction);if(console.log(`Decision: ${decision}`),decision==="deny")process.exit(1)}}async function handleResolve(id,options){if(options.decision!=="allow"&&options.decision!=="deny")console.error('Error: --decision must be "allow" or "deny"'),process.exit(1);let actor=process.env.GENIE_AGENT_NAME||options.by;if(await resolveApproval(id,options.decision,actor))console.log(`Approval ${id} resolved: ${options.decision} by ${options.by}`);else console.error(`Error: Approval ${id} not found or already resolved`),process.exit(1)}async function handleList(options){let rows=await listPendingApprovals(options.agent);if(options.json){console.log(JSON.stringify(rows,null,2));return}if(rows.length===0){console.log("No pending approvals.");return}console.log(` ${"ID".padEnd(38)} ${"AGENT".padEnd(20)} ${"TOOL".padEnd(15)} TIMEOUT`),console.log(` ${"\u2500".repeat(85)}`);for(let row2 of rows){let timeout=new Date(row2.timeout_at).toLocaleTimeString();console.log(` ${String(row2.id).padEnd(38)} ${String(row2.agent_name).padEnd(20)} ${String(row2.tool_name).padEnd(15)} ${timeout}`)}console.log(`
4145
4148
  ${rows.length} pending approval${rows.length===1?"":"s"}`)}function registerApprovalCommands(program2){let approval=program2.command("approval").description("Remote approval queue management");approval.command("request").description("Create an approval request (for tmux-path agents)").requiredOption("--tool <name>","Tool name requiring approval").requiredOption("--input <preview>","Tool input preview text").requiredOption("--agent <name>","Agent name requesting approval").option("--wait","Block until the approval is resolved").option("--timeout <seconds>","Timeout in seconds (overrides workspace config)").action(async(options)=>{try{await handleRequest(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),approval.command("resolve <id>").description("Resolve a pending approval").requiredOption("--decision <decision>","Decision: allow or deny").option("--by <actor>",'Display label for decision maker (defaults to GENIE_AGENT_NAME or "cli")',"cli").action(async(id,options)=>{try{await handleResolve(id,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),approval.command("list").description("List pending approvals").option("--agent <name>","Filter by agent name").option("--json","Output as JSON").action(async(options)=>{try{await handleList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_audit();init_db();var V2_SELECT=`
4146
4149
  id,
@@ -4241,8 +4244,8 @@ Registering in Omni (${omniUrl})...`);let existingId=await findOmniAgent(name);i
4241
4244
  text, data, thread_id, trace_id, parent_event_id, created_at
4242
4245
  ) VALUES (
4243
4246
  $1, $2, $3, $4, $5, $6, NULL, NULL, $7, $8::jsonb, NULL, NULL, NULL, $9::timestamptz
4244
- )`,[process.env.GENIE_REPO_PATH??process.cwd(),MIGRATE_SUBJECT,"system",MIGRATE_SOURCE,row2.actor??"legacy",null,row2.event_type,JSON.stringify(buildEnrichedData(row2)),createdAt])}async function applyBatch(sql,batch,stats2,limit){let cursorId=0;for(let row2 of batch){if(stats2.migrated>=limit)break;try{await insertMigratedRow(sql,row2),stats2.migrated+=1}catch{stats2.skipped+=1}cursorId=row2.legacy_id}return cursorId}async function runAuditMigration(options){let sql=await getConnection(),sinceTs=options.since?parseSince3(options.since):null,total=await countTotalRows(sql,sinceTs),already=await countAlreadyMigrated(sql,sinceTs),toMigrate=total-already,stats2={total_audit_rows:total,already_migrated:already,to_migrate:Math.max(0,toMigrate),migrated:0,skipped:0,dry_run:Boolean(options.dryRun)};if(options.dryRun||toMigrate<=0)return stats2;let limit=options.limit??Number.POSITIVE_INFINITY,cursorId=0;while(stats2.migrated<limit){let batch=await fetchBatch(sql,cursorId,sinceTs);if(batch.length===0)break;if(cursorId=await applyBatch(sql,batch,stats2,limit),batch.length<BATCH_SIZE2)break}return stats2}function normalizeDetails(raw){if(!raw)return{};if(typeof raw==="string")try{let parsed=JSON.parse(raw);return typeof parsed==="object"&&parsed!==null?parsed:{_raw:raw}}catch{return{_raw:raw}}return raw}async function migrateCommand2(options){if(!options.audit)console.error("Usage: genie events migrate --audit [--dry-run] [--since <dur>] [--limit <n>]"),process.exit(1);try{let stats2=await runAuditMigration(options);if(options.json){console.log(JSON.stringify(stats2,null,2));return}if(console.log(color("brightCyan",`Audit Migration${options.dryRun?" (dry-run)":""}`)),console.log(color("dim","\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(`Total audit_events: ${stats2.total_audit_rows}`),console.log(`Already migrated: ${stats2.already_migrated}`),console.log(`To migrate: ${stats2.to_migrate}`),!options.dryRun){if(console.log(`Migrated: ${stats2.migrated}`),stats2.skipped>0)console.log(color("yellow",`Skipped (errors): ${stats2.skipped}`))}}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Migration failed: ${msg}`),process.exit(1)}}init_emit();import{randomUUID as randomUUID12}from"crypto";import{existsSync as existsSync54,mkdirSync as mkdirSync24,readFileSync as readFileSync36,renameSync as renameSync9,writeFileSync as writeFileSync23}from"fs";import{homedir as homedir44}from"os";import{join as join66}from"path";function genieHome4(){return process.env.GENIE_HOME??join66(homedir44(),".genie")}function stateDir(){return join66(genieHome4(),"state")}function statePath(consumerId){return join66(stateDir(),`consumer-${sanitizeId(consumerId)}.json`)}function sanitizeId(id){return id.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,128)}function generateConsumerId(prefix="stream"){let uuid=randomUUID12().replace(/-/g,"").slice(0,12);return`${prefix}-${uuid}`}function loadConsumerState(consumerId){let path3=statePath(consumerId);if(!existsSync54(path3))return null;try{let raw=readFileSync36(path3,"utf-8"),parsed=JSON.parse(raw);if(!parsed||typeof parsed!=="object")return null;if(typeof parsed.consumer_id!=="string"||parsed.consumer_id!==consumerId)return null;if(typeof parsed.last_seen_id!=="number"||!Number.isFinite(parsed.last_seen_id))return null;return{consumer_id:parsed.consumer_id,last_seen_id:parsed.last_seen_id,updated_at:typeof parsed.updated_at==="string"?parsed.updated_at:new Date().toISOString(),filters:parsed.filters}}catch{return null}}function saveConsumerState(state){let dir=stateDir();if(!existsSync54(dir))mkdirSync24(dir,{recursive:!0});let target=statePath(state.consumer_id),tmp=`${target}.${process.pid}.tmp`;writeFileSync23(tmp,`${JSON.stringify({...state,updated_at:new Date().toISOString()},null,2)}
4245
- `,"utf-8"),renameSync9(tmp,target)}init_term_format();async function resolveTokenPayload(options){let tokenStr=options.token??process.env.GENIE_EVENTS_TOKEN;if(tokenStr&&!options.skipTokenCheck)try{return await verifyToken(tokenStr)}catch(err){if(err instanceof TokenError)console.error(color("red",`token rejected: ${err.code} \u2014 ${err.message}`)),process.exit(2);throw err}if(process.env.GENIE_EVENTS_TOKEN_REQUIRED==="1"&&!options.skipTokenCheck)console.error(color("red","GENIE_EVENTS_TOKEN required but not provided")),process.exit(2);return null}function resolvePrefixes(options,tokenPayload){let baseprefixes=options.kind?[options.kind]:[...DEFAULT_CHANNEL_PREFIXES],tokenPrefixes=tokenPayload?tokenPayload.allowed_channels.map((c)=>c.replace(/^genie_events\./,"")):null,prefixesToListen=tokenPrefixes?baseprefixes.filter((p)=>tokenPrefixes.includes(p)):baseprefixes;if(tokenPrefixes&&prefixesToListen.length===0)console.error(color("red",`token allow-list ${JSON.stringify(tokenPrefixes)} does not intersect requested prefix(es) ${JSON.stringify(baseprefixes)}`)),process.exit(2);return prefixesToListen}function emitGapEvent(consumerId,fromId,toId){try{emitEvent("stream.gap.detected",{consumer_id:consumerId,from_id:fromId,to_id:toId,missing_count:toId-fromId+1},{severity:"warn",source_subsystem:"consumer-stream"})}catch{}}function isTypeAllowed(tokenPayload,subject){if(!tokenPayload)return!0;let allowed=tokenPayload.allowed_types;if(!Array.isArray(allowed)||allowed.length===0)return!0;return allowed.includes(subject??"")}function persistCursor(consumerId,lastSeenId,options){try{saveConsumerState({consumer_id:consumerId,last_seen_id:lastSeenId,updated_at:new Date().toISOString(),filters:{kind:options.kind,severity:options.severity,since:options.since}})}catch{}}async function drainOnce(ctx){if(!ctx.isActive())return;let startId=ctx.getLastSeenId(),batch=await queryV2Batch({afterId:startId,kindPrefix:ctx.options.kind,severity:ctx.options.severity,since:ctx.options.since,limit:500});for(let row2 of batch){let prev=ctx.getLastSeenId();if(row2.id>prev+1&&prev>0)emitGapEvent(ctx.consumerId,prev+1,row2.id-1);if(ctx.setLastSeenId(row2.id),!isTypeAllowed(ctx.tokenPayload,row2.subject))continue;try{ctx.onEvent(row2);let delivered=ctx.incrementDelivered();if(ctx.options.maxEvents&&delivered>=ctx.options.maxEvents){ctx.deactivate();break}}catch{}}if(batch.length>0)persistCursor(ctx.consumerId,ctx.getLastSeenId(),ctx.options)}async function runEventsStreamFollow(options,onEvent){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2(),tokenPayload=await resolveTokenPayload(options),consumerId=options.consumerId??tokenPayload?.subscriber_id??generateConsumerId("stream"),lastSeenId=loadConsumerState(consumerId)?.last_seen_id??await getLatestEventId(),eventsDelivered=0,active=!0,drainChain=Promise.resolve(),prefixesToListen=resolvePrefixes(options,tokenPayload),ctx={options,consumerId,tokenPayload,onEvent,getLastSeenId:()=>lastSeenId,setLastSeenId:(id)=>{lastSeenId=id},incrementDelivered:()=>++eventsDelivered,isActive:()=>active,deactivate:()=>{active=!1}},queueDrain=()=>{drainChain=drainChain.then(()=>drainOnce(ctx)).catch(()=>{})},listeners2=[];for(let prefix of prefixesToListen){let channel=`genie_events.${prefix}`;try{let listener=await sql.listen(channel,()=>{queueDrain()});listeners2.push(listener)}catch{}}let pollTimer=setInterval(queueDrain,2000),heartbeatMs=options.heartbeatIntervalMs??30000,heartbeatTimer=setInterval(()=>{try{emitEvent("consumer.heartbeat",{consumer_id:consumerId,last_event_id_processed:lastSeenId,backlog_depth:0},{severity:"debug",source_subsystem:"consumer-stream"})}catch{}},heartbeatMs);queueDrain();let idleTimer=null;if(options.idleExitMs)idleTimer=setTimeout(()=>{active=!1},options.idleExitMs);return{stop:async()=>{if(active=!1,clearInterval(pollTimer),clearInterval(heartbeatTimer),idleTimer)clearTimeout(idleTimer);try{await drainChain}catch{}for(let l of listeners2)try{await l.unlisten()}catch{}persistCursor(consumerId,lastSeenId,options)},getLastSeenId:()=>lastSeenId,getEventsDelivered:()=>eventsDelivered}}function formatRowPretty(row2){let ts3=new Date(row2.created_at).toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}),subject=row2.subject??row2.text??"unknown",severity=row2.severity??"-",sevColor=severity==="error"||severity==="fatal"?color("red",severity):severity==="warn"?color("yellow",severity):severity==="debug"?color("dim",severity):color("cyan",severity),trace=row2.trace_id?color("dim",` trace=${row2.trace_id.slice(0,8)}`):"",duration=row2.duration_ms!=null?` ${color("dim",`${row2.duration_ms}ms`)}`:"";return`${color("dim",ts3)} ${sevColor.padEnd(5)} ${color("brightCyan",subject)}${duration}${trace}`}function printRow(row2,json2){console.log(json2?JSON.stringify(row2):formatRowPretty(row2))}async function runStreamOnce(options){let latest=await getLatestEventId(),batch=await queryV2Batch({afterId:Math.max(0,latest-100),kindPrefix:options.kind,severity:options.severity,since:options.since,limit:500});for(let row2 of batch)printRow(row2,options.json)}function printStreamHeader(options){if(options.json)return;let filterDesc=[];if(options.kind)filterDesc.push(`kind=${options.kind}`);if(options.severity)filterDesc.push(`severity=${options.severity}`);if(options.since)filterDesc.push(`since=${options.since}`);let suffix=filterDesc.length>0?` [${filterDesc.join(", ")}]`:"";console.log(color("dim",`Streaming genie_runtime_events${suffix} (Ctrl+C to stop)...`))}async function streamCommand(options){if(!options.follow){await runStreamOnce(options);return}printStreamHeader(options);let handle=await runEventsStreamFollow(options,(row2)=>printRow(row2,options.json)),shutdown3=async()=>{await handle.stop(),process.exit(0)};process.on("SIGINT",shutdown3),process.on("SIGTERM",shutdown3),await new Promise(()=>{})}init_term_format();function parseDuration2(dur,defaultSeconds){if(!dur)return defaultSeconds;let match=dur.match(/^(\d+)([smhd])$/);if(!match){let n=Number.parseInt(dur,10);return Number.isFinite(n)?n:defaultSeconds}let amount=Number.parseInt(match[1],10),unit=match[2],mult={s:1,m:60,h:3600,d:86400}[unit];return amount*mult}function parseCsv(csv){if(!csv)return[];return csv.split(",").map((s2)=>s2.trim()).filter((s2)=>s2.length>0)}function validateRole(role){if(!role||!ALL_ROLES.includes(role))throw Error(`--role is required and must be one of: ${ALL_ROLES.join(", ")}`);return role}async function subscribeCommand(options){let role=validateRole(options.role),types4=parseCsv(options.types),channels=parseCsv(options.channels),ttlSeconds=parseDuration2(options.ttl,3600),derivedChannels=channels.length>0?channels:types4.length>0?Array.from(new Set(types4.map((t)=>`genie_events.${t.split(".")[0]}`))):[...allowedChannels(role)];try{let{token,payload}=mintToken2({role,allowed_types:types4,allowed_channels:derivedChannels,tenant_id:options.tenant,subscriber_id:options.subscriberId,ttl_seconds:ttlSeconds});if(options.json)console.log(JSON.stringify({token,payload},null,2));else console.log(color("dim",`# genie events subscribe --role ${role}`)),console.log(color("brightCyan",`subscriber_id: ${payload.subscriber_id}`)),console.log(color("dim",`token_id: ${payload.token_id}`)),console.log(color("dim",`role: ${payload.role}`)),console.log(color("dim",`tenant_id: ${payload.tenant_id}`)),console.log(color("dim",`allowed_types: ${payload.allowed_types.length>0?payload.allowed_types.join(","):"(role default)"}`)),console.log(color("dim",`channels: ${payload.allowed_channels.join(",")}`)),console.log(color("dim",`expires_at: ${new Date(payload.exp*1000).toISOString()}`)),console.log(""),console.log(color("green","export GENIE_EVENTS_TOKEN=\\")),console.log(token);return{token,payload}}catch(err){if(err instanceof RBACError)console.error(color("red",`RBAC denied: ${err.message}`)),process.exit(2);throw err}}init_db();init_term_format();var TIMELINE_CTE=`
4247
+ )`,[process.env.GENIE_REPO_PATH??process.cwd(),MIGRATE_SUBJECT,"system",MIGRATE_SOURCE,row2.actor??"legacy",null,row2.event_type,JSON.stringify(buildEnrichedData(row2)),createdAt])}async function applyBatch(sql,batch,stats2,limit){let cursorId=0;for(let row2 of batch){if(stats2.migrated>=limit)break;try{await insertMigratedRow(sql,row2),stats2.migrated+=1}catch{stats2.skipped+=1}cursorId=row2.legacy_id}return cursorId}async function runAuditMigration(options){let sql=await getConnection(),sinceTs=options.since?parseSince3(options.since):null,total=await countTotalRows(sql,sinceTs),already=await countAlreadyMigrated(sql,sinceTs),toMigrate=total-already,stats2={total_audit_rows:total,already_migrated:already,to_migrate:Math.max(0,toMigrate),migrated:0,skipped:0,dry_run:Boolean(options.dryRun)};if(options.dryRun||toMigrate<=0)return stats2;let limit=options.limit??Number.POSITIVE_INFINITY,cursorId=0;while(stats2.migrated<limit){let batch=await fetchBatch(sql,cursorId,sinceTs);if(batch.length===0)break;if(cursorId=await applyBatch(sql,batch,stats2,limit),batch.length<BATCH_SIZE2)break}return stats2}function normalizeDetails(raw){if(!raw)return{};if(typeof raw==="string")try{let parsed=JSON.parse(raw);return typeof parsed==="object"&&parsed!==null?parsed:{_raw:raw}}catch{return{_raw:raw}}return raw}async function migrateCommand2(options){if(!options.audit)console.error("Usage: genie events migrate --audit [--dry-run] [--since <dur>] [--limit <n>]"),process.exit(1);try{let stats2=await runAuditMigration(options);if(options.json){console.log(JSON.stringify(stats2,null,2));return}if(console.log(color("brightCyan",`Audit Migration${options.dryRun?" (dry-run)":""}`)),console.log(color("dim","\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(`Total audit_events: ${stats2.total_audit_rows}`),console.log(`Already migrated: ${stats2.already_migrated}`),console.log(`To migrate: ${stats2.to_migrate}`),!options.dryRun){if(console.log(`Migrated: ${stats2.migrated}`),stats2.skipped>0)console.log(color("yellow",`Skipped (errors): ${stats2.skipped}`))}}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Migration failed: ${msg}`),process.exit(1)}}init_emit();import{randomUUID as randomUUID12}from"crypto";import{existsSync as existsSync54,mkdirSync as mkdirSync24,readFileSync as readFileSync36,renameSync as renameSync10,writeFileSync as writeFileSync23}from"fs";import{homedir as homedir44}from"os";import{join as join66}from"path";function genieHome4(){return process.env.GENIE_HOME??join66(homedir44(),".genie")}function stateDir(){return join66(genieHome4(),"state")}function statePath(consumerId){return join66(stateDir(),`consumer-${sanitizeId(consumerId)}.json`)}function sanitizeId(id){return id.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,128)}function generateConsumerId(prefix="stream"){let uuid=randomUUID12().replace(/-/g,"").slice(0,12);return`${prefix}-${uuid}`}function loadConsumerState(consumerId){let path3=statePath(consumerId);if(!existsSync54(path3))return null;try{let raw=readFileSync36(path3,"utf-8"),parsed=JSON.parse(raw);if(!parsed||typeof parsed!=="object")return null;if(typeof parsed.consumer_id!=="string"||parsed.consumer_id!==consumerId)return null;if(typeof parsed.last_seen_id!=="number"||!Number.isFinite(parsed.last_seen_id))return null;return{consumer_id:parsed.consumer_id,last_seen_id:parsed.last_seen_id,updated_at:typeof parsed.updated_at==="string"?parsed.updated_at:new Date().toISOString(),filters:parsed.filters}}catch{return null}}function saveConsumerState(state){let dir=stateDir();if(!existsSync54(dir))mkdirSync24(dir,{recursive:!0});let target=statePath(state.consumer_id),tmp=`${target}.${process.pid}.tmp`;writeFileSync23(tmp,`${JSON.stringify({...state,updated_at:new Date().toISOString()},null,2)}
4248
+ `,"utf-8"),renameSync10(tmp,target)}init_term_format();async function resolveTokenPayload(options){let tokenStr=options.token??process.env.GENIE_EVENTS_TOKEN;if(tokenStr&&!options.skipTokenCheck)try{return await verifyToken(tokenStr)}catch(err){if(err instanceof TokenError)console.error(color("red",`token rejected: ${err.code} \u2014 ${err.message}`)),process.exit(2);throw err}if(process.env.GENIE_EVENTS_TOKEN_REQUIRED==="1"&&!options.skipTokenCheck)console.error(color("red","GENIE_EVENTS_TOKEN required but not provided")),process.exit(2);return null}function resolvePrefixes(options,tokenPayload){let baseprefixes=options.kind?[options.kind]:[...DEFAULT_CHANNEL_PREFIXES],tokenPrefixes=tokenPayload?tokenPayload.allowed_channels.map((c)=>c.replace(/^genie_events\./,"")):null,prefixesToListen=tokenPrefixes?baseprefixes.filter((p)=>tokenPrefixes.includes(p)):baseprefixes;if(tokenPrefixes&&prefixesToListen.length===0)console.error(color("red",`token allow-list ${JSON.stringify(tokenPrefixes)} does not intersect requested prefix(es) ${JSON.stringify(baseprefixes)}`)),process.exit(2);return prefixesToListen}function emitGapEvent(consumerId,fromId,toId){try{emitEvent("stream.gap.detected",{consumer_id:consumerId,from_id:fromId,to_id:toId,missing_count:toId-fromId+1},{severity:"warn",source_subsystem:"consumer-stream"})}catch{}}function isTypeAllowed(tokenPayload,subject){if(!tokenPayload)return!0;let allowed=tokenPayload.allowed_types;if(!Array.isArray(allowed)||allowed.length===0)return!0;return allowed.includes(subject??"")}function persistCursor(consumerId,lastSeenId,options){try{saveConsumerState({consumer_id:consumerId,last_seen_id:lastSeenId,updated_at:new Date().toISOString(),filters:{kind:options.kind,severity:options.severity,since:options.since}})}catch{}}async function drainOnce(ctx){if(!ctx.isActive())return;let startId=ctx.getLastSeenId(),batch=await queryV2Batch({afterId:startId,kindPrefix:ctx.options.kind,severity:ctx.options.severity,since:ctx.options.since,limit:500});for(let row2 of batch){let prev=ctx.getLastSeenId();if(row2.id>prev+1&&prev>0)emitGapEvent(ctx.consumerId,prev+1,row2.id-1);if(ctx.setLastSeenId(row2.id),!isTypeAllowed(ctx.tokenPayload,row2.subject))continue;try{ctx.onEvent(row2);let delivered=ctx.incrementDelivered();if(ctx.options.maxEvents&&delivered>=ctx.options.maxEvents){ctx.deactivate();break}}catch{}}if(batch.length>0)persistCursor(ctx.consumerId,ctx.getLastSeenId(),ctx.options)}async function runEventsStreamFollow(options,onEvent){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2(),tokenPayload=await resolveTokenPayload(options),consumerId=options.consumerId??tokenPayload?.subscriber_id??generateConsumerId("stream"),lastSeenId=loadConsumerState(consumerId)?.last_seen_id??await getLatestEventId(),eventsDelivered=0,active=!0,drainChain=Promise.resolve(),prefixesToListen=resolvePrefixes(options,tokenPayload),ctx={options,consumerId,tokenPayload,onEvent,getLastSeenId:()=>lastSeenId,setLastSeenId:(id)=>{lastSeenId=id},incrementDelivered:()=>++eventsDelivered,isActive:()=>active,deactivate:()=>{active=!1}},queueDrain=()=>{drainChain=drainChain.then(()=>drainOnce(ctx)).catch(()=>{})},listeners2=[];for(let prefix of prefixesToListen){let channel=`genie_events.${prefix}`;try{let listener=await sql.listen(channel,()=>{queueDrain()});listeners2.push(listener)}catch{}}let pollTimer=setInterval(queueDrain,2000),heartbeatMs=options.heartbeatIntervalMs??30000,heartbeatTimer=setInterval(()=>{try{emitEvent("consumer.heartbeat",{consumer_id:consumerId,last_event_id_processed:lastSeenId,backlog_depth:0},{severity:"debug",source_subsystem:"consumer-stream"})}catch{}},heartbeatMs);queueDrain();let idleTimer=null;if(options.idleExitMs)idleTimer=setTimeout(()=>{active=!1},options.idleExitMs);return{stop:async()=>{if(active=!1,clearInterval(pollTimer),clearInterval(heartbeatTimer),idleTimer)clearTimeout(idleTimer);try{await drainChain}catch{}for(let l of listeners2)try{await l.unlisten()}catch{}persistCursor(consumerId,lastSeenId,options)},getLastSeenId:()=>lastSeenId,getEventsDelivered:()=>eventsDelivered}}function formatRowPretty(row2){let ts3=new Date(row2.created_at).toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}),subject=row2.subject??row2.text??"unknown",severity=row2.severity??"-",sevColor=severity==="error"||severity==="fatal"?color("red",severity):severity==="warn"?color("yellow",severity):severity==="debug"?color("dim",severity):color("cyan",severity),trace=row2.trace_id?color("dim",` trace=${row2.trace_id.slice(0,8)}`):"",duration=row2.duration_ms!=null?` ${color("dim",`${row2.duration_ms}ms`)}`:"";return`${color("dim",ts3)} ${sevColor.padEnd(5)} ${color("brightCyan",subject)}${duration}${trace}`}function printRow(row2,json2){console.log(json2?JSON.stringify(row2):formatRowPretty(row2))}async function runStreamOnce(options){let latest=await getLatestEventId(),batch=await queryV2Batch({afterId:Math.max(0,latest-100),kindPrefix:options.kind,severity:options.severity,since:options.since,limit:500});for(let row2 of batch)printRow(row2,options.json)}function printStreamHeader(options){if(options.json)return;let filterDesc=[];if(options.kind)filterDesc.push(`kind=${options.kind}`);if(options.severity)filterDesc.push(`severity=${options.severity}`);if(options.since)filterDesc.push(`since=${options.since}`);let suffix=filterDesc.length>0?` [${filterDesc.join(", ")}]`:"";console.log(color("dim",`Streaming genie_runtime_events${suffix} (Ctrl+C to stop)...`))}async function streamCommand(options){if(!options.follow){await runStreamOnce(options);return}printStreamHeader(options);let handle=await runEventsStreamFollow(options,(row2)=>printRow(row2,options.json)),shutdown3=async()=>{await handle.stop(),process.exit(0)};process.on("SIGINT",shutdown3),process.on("SIGTERM",shutdown3),await new Promise(()=>{})}init_term_format();function parseDuration2(dur,defaultSeconds){if(!dur)return defaultSeconds;let match=dur.match(/^(\d+)([smhd])$/);if(!match){let n=Number.parseInt(dur,10);return Number.isFinite(n)?n:defaultSeconds}let amount=Number.parseInt(match[1],10),unit=match[2],mult={s:1,m:60,h:3600,d:86400}[unit];return amount*mult}function parseCsv(csv){if(!csv)return[];return csv.split(",").map((s2)=>s2.trim()).filter((s2)=>s2.length>0)}function validateRole(role){if(!role||!ALL_ROLES.includes(role))throw Error(`--role is required and must be one of: ${ALL_ROLES.join(", ")}`);return role}async function subscribeCommand(options){let role=validateRole(options.role),types4=parseCsv(options.types),channels=parseCsv(options.channels),ttlSeconds=parseDuration2(options.ttl,3600),derivedChannels=channels.length>0?channels:types4.length>0?Array.from(new Set(types4.map((t)=>`genie_events.${t.split(".")[0]}`))):[...allowedChannels(role)];try{let{token,payload}=mintToken2({role,allowed_types:types4,allowed_channels:derivedChannels,tenant_id:options.tenant,subscriber_id:options.subscriberId,ttl_seconds:ttlSeconds});if(options.json)console.log(JSON.stringify({token,payload},null,2));else console.log(color("dim",`# genie events subscribe --role ${role}`)),console.log(color("brightCyan",`subscriber_id: ${payload.subscriber_id}`)),console.log(color("dim",`token_id: ${payload.token_id}`)),console.log(color("dim",`role: ${payload.role}`)),console.log(color("dim",`tenant_id: ${payload.tenant_id}`)),console.log(color("dim",`allowed_types: ${payload.allowed_types.length>0?payload.allowed_types.join(","):"(role default)"}`)),console.log(color("dim",`channels: ${payload.allowed_channels.join(",")}`)),console.log(color("dim",`expires_at: ${new Date(payload.exp*1000).toISOString()}`)),console.log(""),console.log(color("green","export GENIE_EVENTS_TOKEN=\\")),console.log(token);return{token,payload}}catch(err){if(err instanceof RBACError)console.error(color("red",`RBAC denied: ${err.message}`)),process.exit(2);throw err}}init_db();init_term_format();var TIMELINE_CTE=`
4246
4249
  WITH RECURSIVE
4247
4250
  base AS (
4248
4251
  SELECT
@@ -4283,15 +4286,15 @@ Registering in Omni (${omniUrl})...`);let existingId=await findOmniAgent(name);i
4283
4286
  (${rows.length} event${rows.length===1?"":"s"})`)}async function eventsListV2Command(options){try{let limit=options.limit?Number.parseInt(options.limit,10):50,rows=await queryV2Batch({kindPrefix:options.kind,severity:options.severity,since:options.since??"1h",limit});if(options.json)console.log(JSON.stringify(rows,null,2));else if(printV2EventsTable(rows),isOtelKindFilter(options.kind))printOtelScopeWarning({empty:rows.length===0})}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying v2 events: ${msg}`),process.exit(1)}}async function eventsListCommand(options){if(options.enriched||options.v2){if(options.v2&&!options.enriched)console.error("\u26A0\uFE0F `events list --v2` is deprecated; use `events list --enriched`.");return eventsListV2Command(options)}try{let queryOpts={type:options.type,entity:options.entity,since:options.since??"1h",errorsOnly:options.errorsOnly,limit:options.limit?Number.parseInt(options.limit,10):50};if(options.follow){let{followAuditEvents:followAuditEvents2}=await Promise.resolve().then(() => (init_audit(),exports_audit));console.log("Following audit events (Ctrl+C to stop)...");let handle=await followAuditEvents2(queryOpts,(row2)=>{if(options.json)console.log(JSON.stringify(row2));else{let time=formatRelativeTimestamp(row2.created_at),entity=`${row2.entity_type}:${row2.entity_id}`.slice(0,40),event=row2.event_type.padEnd(24),details=summarizeDetails(row2.details).slice(0,60);console.log(`${time} ${event} ${entity} ${details}`)}}),shutdown3=()=>{handle.stop(),process.exit(0)};process.on("SIGINT",shutdown3),process.on("SIGTERM",shutdown3),await new Promise(()=>{});return}let rows=await queryAuditEvents(queryOpts);if(options.json)console.log(JSON.stringify(rows,null,2));else if(printEventsTable(rows),isOtelTypeFilter(options.type))printOtelScopeWarning({empty:rows.length===0})}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying events: ${msg}`),process.exit(1)}}var DEFAULT_HIDDEN_EVENT_TYPES=new Set(["command_success","sdk.hook.started"]);async function eventsStreamCommand(options){let{followAuditEvents:followAuditEvents2}=await Promise.resolve().then(() => (init_audit(),exports_audit)),{followRuntimeEvents:followRuntimeEvents2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events)),{color:color2}=await Promise.resolve().then(() => (init_term_format(),exports_term_format)),{renderAuditEvent:renderAuditEvent2,renderRuntimeEvent:renderRuntimeEvent2,formatEventLine:formatEventLine2}=await Promise.resolve().then(() => (init_event_renderer(),exports_event_renderer)),handles2=[],clockTime=(iso)=>{return(iso instanceof Date?iso:new Date(iso)).toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})};if(!options.json){let sources=options.auditOnly?"audit":options.runtimeOnly?"runtime":"audit + runtime";console.log(color2("dim",`Streaming ${sources} events (Ctrl+C to stop)...`))}if(!options.runtimeOnly){let auditHandle=await followAuditEvents2({type:options.type,entity:options.entity,errorsOnly:options.errorsOnly},(row2)=>{if(!options.all&&!options.type&&DEFAULT_HIDDEN_EVENT_TYPES.has(row2.event_type))return;if(options.json){console.log(JSON.stringify({stream:"audit",...row2}));return}console.log(formatEventLine2(clockTime(row2.created_at),renderAuditEvent2({entity_type:row2.entity_type,entity_id:row2.entity_id,event_type:row2.event_type,details:row2.details})))});handles2.push(auditHandle)}if(!options.auditOnly){let validKinds=["user","assistant","message","state","tool_call","tool_result","system","qa"],kinds=options.kind&&validKinds.includes(options.kind)?[options.kind]:void 0,agentIds=options.agent?[options.agent]:void 0,runtimeHandle=await followRuntimeEvents2({kinds,agentIds,scopeMode:"any"},(event)=>{if(options.json){console.log(JSON.stringify({stream:"runtime",...event}));return}console.log(formatEventLine2(clockTime(event.timestamp),renderRuntimeEvent2({kind:event.kind,agent:event.agent,team:event.team,text:event.text})))},{pollIntervalMs:2000});handles2.push(runtimeHandle)}let shutdown3=async()=>{for(let h of handles2)await h.stop();process.exit(0)};process.on("SIGINT",shutdown3),process.on("SIGTERM",shutdown3),await new Promise(()=>{})}async function eventsErrorsCommand(options){try{let patterns2=await queryErrorPatterns(options.since);if(options.json)console.log(JSON.stringify(patterns2,null,2));else printErrorsTable(patterns2)}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying error patterns: ${msg}`),process.exit(1)}}function resolveCostsGroupBy(options){if(options.byWish)return"wish";if(options.byModel)return"model";return"agent"}function printCostsTable(rows,groupBy){if(rows.length===0){console.log("No cost data found.");return}let headers=[groupBy==="agent"?"Agent":groupBy==="wish"?"Wish":"Model","Total Cost","Requests","Avg Cost"],data=rows.map((r)=>[r.group_key,`$${r.total_cost.toFixed(4)}`,String(r.request_count),`$${r.avg_cost.toFixed(4)}`]),widths=headers.map((h,i2)=>{let colVals=data.map((row2)=>row2[i2]);return Math.min(40,Math.max(h.length,...colVals.map((v)=>v.length)))});console.log(headers.map((h,i2)=>padRight(h,widths[i2])).join(" | ")),console.log(widths.map((w)=>"-".repeat(w)).join("-+-"));for(let row2 of data)console.log(row2.map((v,i2)=>padRight(v.slice(0,widths[i2]),widths[i2])).join(" | "));let totalCost=rows.reduce((sum,r)=>sum+r.total_cost,0),totalReqs=rows.reduce((sum,r)=>sum+r.request_count,0);console.log(`
4284
4287
  Total: $${totalCost.toFixed(4)} across ${totalReqs} requests`)}async function eventsCostsCommand(options){try{let since=options.today?"24h":options.since??"24h",groupBy=resolveCostsGroupBy(options),rows=await queryCostBreakdown(since,groupBy);if(options.json)console.log(JSON.stringify(rows,null,2));else if(printCostsTable(rows,groupBy),printOtelScopeWarning({empty:rows.length===0}),rows.length>0)console.log(" For full server costs: npx ccusage monthly")}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying costs: ${msg}`),process.exit(1)}}function printToolsDetailTable(rows){if(rows.length===0){console.log("No tool invocations found.");return}let headers=["Time","Tool","Agent","Duration","Input"],data=rows.map((r)=>[formatRelativeTimestamp(typeof r.created_at==="string"?r.created_at:r.created_at.toISOString()),r.tool_name??r.entity_id,r.actor??"-",r.duration_ms!=null?`${Number(r.duration_ms).toFixed(0)}ms`:"-",previewJson(r.tool_input??r.tool_parameters)]),widths=headers.map((h,i2)=>{let colVals=data.map((row2)=>row2[i2]);return Math.min(60,Math.max(h.length,...colVals.map((v)=>v.length)))});console.log(headers.map((h,i2)=>padRight(h,widths[i2])).join(" | ")),console.log(widths.map((w)=>"-".repeat(w)).join("-+-"));for(let row2 of data)console.log(row2.map((v,i2)=>padRight(v.slice(0,widths[i2]),widths[i2])).join(" | "));console.log(`
4285
4288
  (${rows.length} row${rows.length===1?"":"s"})`)}function previewJson(value){if(value==null)return"-";try{return(typeof value==="string"?value:JSON.stringify(value)).replace(/\s+/g," ").slice(0,60)}catch{return"-"}}function printToolsTable(rows,groupBy){if(rows.length===0){console.log("No tool usage data found.");return}let headers=[groupBy==="tool"?"Tool":"Agent","Calls","Success","Errors","Avg Duration"],data=rows.map((r)=>[r.group_key,String(r.total_calls),String(r.success_count),String(r.error_count),r.avg_duration_ms!=null?`${r.avg_duration_ms.toFixed(0)}ms`:"-"]),widths=headers.map((h,i2)=>{let colVals=data.map((row2)=>row2[i2]);return Math.min(40,Math.max(h.length,...colVals.map((v)=>v.length)))});console.log(headers.map((h,i2)=>padRight(h,widths[i2])).join(" | ")),console.log(widths.map((w)=>"-".repeat(w)).join("-+-"));for(let row2 of data)console.log(row2.map((v,i2)=>padRight(v.slice(0,widths[i2]),widths[i2])).join(" | "));let totalCalls=rows.reduce((sum,r)=>sum+r.total_calls,0);console.log(`
4286
- (${totalCalls} total tool calls)`)}async function eventsToolsDetailCommand(since,options){let limit=options.limit?Number.parseInt(options.limit,10):void 0;if(options.limit&&(!Number.isFinite(limit)||limit<=0))console.error(`Invalid --limit value: ${options.limit}`),process.exit(1);let rows=await queryToolUsageDetail(since,{limit,tool:options.tool,agent:options.agent});if(options.json){console.log(JSON.stringify(rows,null,2));return}printToolsDetailTable(rows),printOtelScopeWarning({empty:rows.length===0})}async function eventsToolsCommand(options){try{let since=options.since??"24h";if(options.detail){await eventsToolsDetailCommand(since,options);return}let groupBy=options.byAgent?"agent":"tool",rows=await queryToolUsage(since,groupBy);if(options.json)console.log(JSON.stringify(rows,null,2));else printToolsTable(rows,groupBy),printOtelScopeWarning({empty:rows.length===0})}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying tool usage: ${msg}`),process.exit(1)}}function parseTimelineSince(raw){let trimmed=raw.trim().toLowerCase();if(trimmed==="all")return null;let match=/^(\d+)\s*(s|m|h|d)$/.exec(trimmed);if(!match)throw Error(`invalid --since value "${raw}". Use e.g. 10m, 24h, 7d, or 'all' for full history.`);let n=Number.parseInt(match[1],10),unit=match[2];return n*{s:1000,m:60000,h:3600000,d:86400000}[unit]}async function eventsTimelineCommand(entityId,options){try{let limit=options.limit?Math.max(1,Number.parseInt(options.limit,10)):void 0;if(options.limit!==void 0&&Number.isNaN(Number(options.limit)))console.error(`Error: invalid --limit value "${options.limit}" (must be a positive integer)`),process.exit(1);let sinceMs=options.since!==void 0?parseTimelineSince(options.since):void 0,rows=await queryTimeline(entityId,{limit,sinceMs});if(options.json)console.log(JSON.stringify(rows,null,2));else printEventsTable(rows)}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying timeline: ${msg}`),process.exit(1)}}function printSummary(summary){console.log("Event Summary"),console.log("============="),console.log(`Total events: ${summary.total_events}`),console.log(`Agents spawned: ${summary.agents_spawned}`),console.log(`Tasks moved: ${summary.tasks_moved}`),console.log(`API requests: ${summary.api_requests}`),console.log(`Tool calls: ${summary.tool_calls}`),console.log(`Total cost: $${summary.total_cost.toFixed(4)}`),console.log(`Errors: ${summary.error_count}`)}async function eventsSummaryCommand(options){try{let since=options.today?"24h":options.since??"24h",summary=await querySummary(since);if(options.json)console.log(JSON.stringify(summary,null,2));else{printSummary(summary);let allOtelEmpty=summary.tool_calls===0&&summary.api_requests===0&&summary.total_cost===0;printOtelScopeWarning({empty:allOtelEmpty})}}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying summary: ${msg}`),process.exit(1)}}async function eventsScanCommand(options){let{spawnSync:spawnSync8}=__require("child_process"),args=["ccusage","monthly"];if(options.since)args.push("--since",options.since);if(options.json)args.push("--json");if(options.breakdown)args.push("--breakdown");let result2=spawnSync8("npx",args,{stdio:options.json?"pipe":"inherit",timeout:30000,env:{...process.env,NODE_NO_WARNINGS:"1"}});if(result2.error)console.error("ccusage not available. Install with: npm install -g ccusage"),console.error("Or run directly: npx ccusage monthly"),process.exit(1);if(options.json&&result2.stdout)process.stdout.write(result2.stdout);if(result2.status!==0)process.exit(result2.status??1)}function registerEventsCommands(program2){let events=program2.command("events").description("Audit event log from PG. OTel-derived data (tools/summary/costs and otel_* list rows) is scoped to genie-spawned agents \u2014 user-initiated Claude Code sessions are not captured unless they export OTLP env vars.");events.command("list",{isDefault:!0}).description("List recent audit events (add --enriched for the genie_runtime_events surface)").option("--type <type>","Filter by event_type").option("--entity <entity>","Filter by entity_type or entity_id").option("--since <duration>","Time window (e.g., 1h, 30m, 2d)","1h").option("--errors-only","Show only error events").option("--limit <n>","Max rows to return","50").option("--json","Output as JSON").option("-f, --follow","Follow mode \u2014 real-time streaming (alias: genie events stream)").option("--enriched","Use enriched genie_runtime_events surface with TraceId/SpanId/Severity/Duration columns").option("--v2","[DEPRECATED] alias for --enriched (removed next release)").option("--kind <prefix>","Filter enriched rows by kind/subject prefix (e.g., mailbox, agent.lifecycle)").option("--severity <level>","Filter enriched rows by severity (debug|info|warn|error|fatal)").action(async(options)=>{await eventsListCommand(options)}),events.command("timeline-v2 <trace-id>").description("Render causal tree for a trace_id from genie_runtime_events (v2 enriched surface)").option("--json","Output as JSON").action(async(traceId,options)=>{await timelineCommand(traceId,options)}),events.command("stream-follow").description("Follow-stream enriched genie_runtime_events via LISTEN/NOTIFY + id-cursor (v2)").option("--follow","Continuously follow the stream",!0).option("--kind <prefix>","Filter by subject/kind prefix (supports `*` globs, e.g. `detector.*`)").option("--severity <level>","Filter by severity (debug|info|warn|error|fatal)").option("--since <duration>","Seed window (e.g., 5m, 1h)").option("--consumer-id <id>","Persistent consumer id for cursor resume").option("--json","Output as NDJSON").action(async(options)=>{await streamCommand({...options,follow:!0})}),events.command("migrate").description("Backfill legacy audit_events rows into genie_runtime_events (one-shot)").option("--audit","Migrate audit_events \u2192 genie_runtime_events with sentinel source tag").option("--dry-run","Report row deltas without writing").option("--since <duration>","Only migrate rows created within this window").option("--limit <n>","Cap the number of rows migrated per run",(v)=>Number.parseInt(v,10)).option("--json","Output summary as JSON").action(async(options)=>{await migrateCommand2(options)}),events.command("stream").description("Stream audit + runtime events in real-time (tail -f style)").option("--type <type>","Filter by event_type").option("--entity <entity>","Filter by entity_type or entity_id").option("--errors-only","Show only error events").option("--kind <kind>","Filter runtime events by kind (tool_call, message, prompt, etc)").option("--agent <agent>","Filter runtime events by agent").option("--audit-only","Stream only audit_events (skip runtime)").option("--runtime-only","Stream only runtime events (skip audit)").option("--all","Show all events including noisy ones (command_success, etc)").option("--json","Output as JSON").action(async(options)=>{await eventsStreamCommand(options)}),events.command("errors").description("Show aggregated error patterns").option("--since <duration>","Time window (e.g., 1h, 24h, 7d)").option("--json","Output as JSON").action(async(options)=>{await eventsErrorsCommand(options)}),events.command("costs").description("Cost breakdown from OTel API request events").option("--today","Show costs from the last 24h").option("--since <duration>","Time window (e.g., 1h, 7d)","24h").option("--by-agent","Group by agent").option("--by-wish","Group by wish").option("--by-model","Group by model").option("--json","Output as JSON").action(async(options)=>{await eventsCostsCommand(options)}),events.command("tools").description("Tool usage analytics from OTel tool events").option("--since <duration>","Time window (e.g., 1h, 7d)","24h").option("--by-tool","Group by tool name (default)").option("--by-agent","Group by agent").option("--detail","Return individual tool invocations (with tool_input / tool_parameters) instead of aggregates").option("--tool <name>","Filter --detail rows by tool name").option("--agent <name>","Filter --detail rows by agent/actor").option("--limit <n>","Max rows for --detail (default 500, max 10000)").option("--json","Output as JSON").action(async(options)=>{await eventsToolsCommand(options)}),events.command("timeline <entity-id>").description("Event timeline for a task, agent, wish, traceId, or session_id (default: last 24h)").option("--json","Output as JSON").option("--limit <n>","Max rows to return (default 200, hard cap 2000)").option("--since <duration>",'Time window \u2014 e.g. 10m, 24h, 7d, or "all" for full history. Default: 24h. '+'"all" reverts to the unbounded scan and may time out on production-sized audit logs.').action(async(entityId,options)=>{await eventsTimelineCommand(entityId,options)}),events.command("summary").description("High-level stats: agents spawned, tasks moved, costs, errors").option("--today","Show summary for the last 24h").option("--since <duration>","Time window (e.g., 1h, 7d)","24h").option("--json","Output as JSON").action(async(options)=>{await eventsSummaryCommand(options)}),events.command("scan").description("Full server cost scan via ccusage (all CC sessions, not just genie-spawned)").option("--since <date>","Start date in YYYYMMDD format").option("--json","Output as JSON").option("--breakdown","Show per-model breakdown").action(async(options)=>{await eventsScanCommand(options)}),events.command("subscribe").description("Mint a signed subscription token for genie events stream --follow").requiredOption("--role <role>","RBAC role: events:admin|events:operator|events:subscriber|events:audit").option("--types <csv>","Comma-separated allowed event types (subset of role defaults)").option("--channels <csv>","Comma-separated allowed LISTEN channels (subset of role defaults)").option("--ttl <duration>","Token time-to-live (e.g., 30m, 1h, 24h). Defaults to 1h.").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--subscriber-id <id>","Stable id for the subscriber agent").option("--json","Output as JSON").action(async(options)=>{await subscribeCommand(options)});let admin=events.command("admin").description("Incident-response admin commands (sentinel H6 audited)");admin.command("revoke-subscriber").description("Add a subscription token to the revocation list").requiredOption("--token-id <id>","Token id from `genie events subscribe` output").option("--subscriber-id <id>","Subscriber id associated with the token").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--reason <text>","IR justification for revocation").option("--json","Output as JSON").action(async(options)=>{await revokeSubscriberCommand(options)}),admin.command("rotate-redaction-keys").description("Rotate redaction + audit HMAC keys, preserving prior versions for lookup").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--new-key <material>","Explicit key material (default: 32 bytes hex from /dev/urandom)").option("--target <scope>","redaction|audit|both (default: both)").option("--json","Output as JSON").action(async(options)=>{await rotateRedactionKeysCommand(options)}),admin.command("un-hash").description("Admin reverse-lookup for a Tier-A hash (emits audit.un_hash)").requiredOption("--namespace <ns>","Hash namespace (e.g., agent, actor, session)").requiredOption("--hashed-value <hash>","Tier-A hash tag to reverse").option("--candidates <csv>","Comma-separated candidate plaintexts to brute-force").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--reason <text>","IR justification (appears in audit.un_hash)").option("--ticket <ref>","Incident ticket reference").option("--json","Output as JSON").action(async(options)=>{await unHashCommand(options)}),admin.command("export-audit").description("Produce a signed audit-chain bundle (emits audit.export)").option("--signed","Require GENIE_AUDIT_EXPORT_SECRET for HMAC signing",!0).option("--since <duration>","Advisory time window (authoritative cursor is --since-id)").option("--since-id <n>","Authoritative id cursor to resume from").option("--limit <n>","Max rows to include").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--output <path>","Write bundle to file; omit to print to stdout").option("--reason <text>","IR justification (appears in audit.export)").option("--json","Output as JSON").action(async(options)=>{await exportAuditCommand(options)}),admin.command("verify-chain").description("Quick chain-integrity check (no export)").option("--since-id <n>","Start id","0").option("--limit <n>","Max rows to verify").option("--json","Output as JSON").action(async(options)=>{await verifyChainCommand(options)}),admin.command("list-revocations").description("List revoked token ids for a tenant").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--json","Output as JSON").action(async(options)=>{await listRevocationsCommand(options)})}init_genie_tokens();init_term_format();import{execSync as execSync11}from"child_process";import{existsSync as existsSync55,mkdirSync as mkdirSync25,readFileSync as readFileSync37,writeFileSync as writeFileSync24}from"fs";import{dirname as dirname23,join as join67}from"path";var _boardService;async function getBoardService(){if(!_boardService)_boardService=await Promise.resolve().then(() => (init_board_service(),exports_board_service));return _boardService}var _taskService3;async function getTaskService3(){if(!_taskService3)_taskService3=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService3}var _templateService;async function getTemplateService(){if(!_templateService)_templateService=await Promise.resolve().then(() => (init_template_service(),exports_template_service));return _templateService}async function resolveProjectId(name){let project=await(await getTaskService3()).getProjectByName(name);if(!project)throw Error(`Project not found: ${name}`);return project.id}async function resolveBoard(name,projectName){let bs=await getBoardService(),projectId;if(projectName)projectId=await resolveProjectId(projectName);let board=await bs.getBoard(name,projectId);if(!board)throw Error(`Board not found: ${name}`);return board}function printBoardTable(boards,projectMap){console.log(` ${padRight("NAME",24)} ${padRight("PROJECT",20)} ${padRight("COLUMNS",10)} CREATED`),console.log(` ${"\u2500".repeat(70)}`);for(let b2 of boards){let projName=b2.projectId?projectMap.get(b2.projectId)??b2.projectId:"-",colCount=String(b2.columns.length),created=formatDate(b2.createdAt);console.log(` ${padRight(truncate2(b2.name,22),24)} ${padRight(truncate2(projName,18),20)} ${padRight(colCount,10)} ${created}`)}console.log(`
4289
+ (${totalCalls} total tool calls)`)}async function eventsToolsDetailCommand(since,options){let limit=options.limit?Number.parseInt(options.limit,10):void 0;if(options.limit&&(!Number.isFinite(limit)||limit<=0))console.error(`Invalid --limit value: ${options.limit}`),process.exit(1);let rows=await queryToolUsageDetail(since,{limit,tool:options.tool,agent:options.agent});if(options.json){console.log(JSON.stringify(rows,null,2));return}printToolsDetailTable(rows),printOtelScopeWarning({empty:rows.length===0})}async function eventsToolsCommand(options){try{let since=options.since??"24h";if(options.detail){await eventsToolsDetailCommand(since,options);return}let groupBy=options.byAgent?"agent":"tool",rows=await queryToolUsage(since,groupBy);if(options.json)console.log(JSON.stringify(rows,null,2));else printToolsTable(rows,groupBy),printOtelScopeWarning({empty:rows.length===0})}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying tool usage: ${msg}`),process.exit(1)}}function parseTimelineSince(raw){let trimmed=raw.trim().toLowerCase();if(trimmed==="all")return null;let match=/^(\d+)\s*(s|m|h|d)$/.exec(trimmed);if(!match)throw Error(`invalid --since value "${raw}". Use e.g. 10m, 24h, 7d, or 'all' for full history.`);let n=Number.parseInt(match[1],10),unit=match[2];return n*{s:1000,m:60000,h:3600000,d:86400000}[unit]}async function eventsTimelineCommand(entityId,options){try{let limit=options.limit?Math.max(1,Number.parseInt(options.limit,10)):void 0;if(options.limit!==void 0&&Number.isNaN(Number(options.limit)))console.error(`Error: invalid --limit value "${options.limit}" (must be a positive integer)`),process.exit(1);let sinceMs=options.since!==void 0?parseTimelineSince(options.since):void 0,rows=await queryTimeline(entityId,{limit,sinceMs});if(options.json)console.log(JSON.stringify(rows,null,2));else printEventsTable(rows)}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying timeline: ${msg}`),process.exit(1)}}function printSummary(summary){console.log("Event Summary"),console.log("============="),console.log(`Total events: ${summary.total_events}`),console.log(`Agents spawned: ${summary.agents_spawned}`),console.log(`Tasks moved: ${summary.tasks_moved}`),console.log(`API requests: ${summary.api_requests}`),console.log(`Tool calls: ${summary.tool_calls}`),console.log(`Total cost: $${summary.total_cost.toFixed(4)}`),console.log(`Errors: ${summary.error_count}`)}async function eventsSummaryCommand(options){try{let since=options.today?"24h":options.since??"24h",summary=await querySummary(since);if(options.json)console.log(JSON.stringify(summary,null,2));else{printSummary(summary);let allOtelEmpty=summary.tool_calls===0&&summary.api_requests===0&&summary.total_cost===0;printOtelScopeWarning({empty:allOtelEmpty})}}catch(err){let msg=err instanceof Error?err.message:String(err);console.error(`Error querying summary: ${msg}`),process.exit(1)}}async function eventsScanCommand(options){let{spawnSync:spawnSync8}=__require("child_process"),args=["ccusage","monthly"];if(options.since)args.push("--since",options.since);if(options.json)args.push("--json");if(options.breakdown)args.push("--breakdown");let result2=spawnSync8("npx",args,{stdio:options.json?"pipe":"inherit",timeout:30000,env:{...process.env,NODE_NO_WARNINGS:"1"}});if(result2.error)console.error("ccusage not available. Install with: npm install -g ccusage"),console.error("Or run directly: npx ccusage monthly"),process.exit(1);if(options.json&&result2.stdout)process.stdout.write(result2.stdout);if(result2.status!==0)process.exit(result2.status??1)}function registerEventsCommands(program2){let events=program2.command("events").description("Audit event log from PG. OTel-derived data (tools/summary/costs and otel_* list rows) is scoped to genie-spawned agents \u2014 user-initiated Claude Code sessions are not captured unless they export OTLP env vars.");events.command("list",{isDefault:!0}).description("List recent audit events (add --enriched for the genie_runtime_events surface)").option("--type <type>","Filter by event_type").option("--entity <entity>","Filter by entity_type or entity_id").option("--since <duration>","Time window (e.g., 1h, 30m, 2d)","1h").option("--errors-only","Show only error events").option("--limit <n>","Max rows to return","50").option("--json","Output as JSON").option("-f, --follow","Follow mode \u2014 real-time streaming (alias: genie events stream)").option("--enriched","Use enriched genie_runtime_events surface with TraceId/SpanId/Severity/Duration columns").option("--v2","[DEPRECATED] alias for --enriched (removed next release)").option("--kind <prefix>","Filter enriched rows by kind/subject prefix (e.g., mailbox, agent.lifecycle)").option("--severity <level>","Filter enriched rows by severity (debug|info|warn|error|fatal)").action(async(options)=>{await eventsListCommand(options)}),events.command("timeline-v2 <trace-id>").description("Render causal tree for a trace_id from genie_runtime_events (v2 enriched surface)").option("--json","Output as JSON").action(async(traceId,options)=>{await timelineCommand(traceId,options)}),events.command("stream-follow").description("Follow-stream enriched genie_runtime_events via LISTEN/NOTIFY + id-cursor (v2)").option("--follow","Continuously follow the stream",!0).option("--kind <prefix>","Filter by subject/kind prefix (supports `*` globs, e.g. `detector.*`)").option("--severity <level>","Filter by severity (debug|info|warn|error|fatal)").option("--since <duration>","Seed window (e.g., 5m, 1h)").option("--consumer-id <id>","Persistent consumer id for cursor resume").option("--json","Output as NDJSON").action(async(options)=>{await streamCommand({...options,follow:!0})}),events.command("migrate").description("Backfill legacy audit_events rows into genie_runtime_events (one-shot)").option("--audit","Migrate audit_events \u2192 genie_runtime_events with sentinel source tag").option("--dry-run","Report row deltas without writing").option("--since <duration>","Only migrate rows created within this window").option("--limit <n>","Cap the number of rows migrated per run",(v)=>Number.parseInt(v,10)).option("--json","Output summary as JSON").action(async(options)=>{await migrateCommand2(options)}),events.command("stream").description("Stream audit + runtime events in real-time (tail -f style)").option("--type <type>","Filter by event_type").option("--entity <entity>","Filter by entity_type or entity_id").option("--errors-only","Show only error events").option("--kind <kind>","Filter runtime events by kind (tool_call, message, prompt, etc)").option("--agent <agent>","Filter runtime events by agent").option("--audit-only","Stream only audit_events (skip runtime)").option("--runtime-only","Stream only runtime events (skip audit)").option("--all","Show all events including noisy ones (command_success, etc)").option("--json","Output as JSON").action(async(options)=>{await eventsStreamCommand(options)}),events.command("errors").description("Show aggregated error patterns").option("--since <duration>","Time window (e.g., 1h, 24h, 7d)").option("--json","Output as JSON").action(async(options)=>{await eventsErrorsCommand(options)}),events.command("costs").description("Cost breakdown from OTel API request events").option("--today","Show costs from the last 24h").option("--since <duration>","Time window (e.g., 1h, 7d)","24h").option("--by-agent","Group by agent").option("--by-wish","Group by wish").option("--by-model","Group by model").option("--json","Output as JSON").action(async(options)=>{await eventsCostsCommand(options)}),events.command("tools").description("Tool usage analytics from OTel tool events").option("--since <duration>","Time window (e.g., 1h, 7d)","24h").option("--by-tool","Group by tool name (default)").option("--by-agent","Group by agent").option("--detail","Return individual tool invocations (with tool_input / tool_parameters) instead of aggregates").option("--tool <name>","Filter --detail rows by tool name").option("--agent <name>","Filter --detail rows by agent/actor").option("--limit <n>","Max rows for --detail (default 500, max 10000)").option("--json","Output as JSON").action(async(options)=>{await eventsToolsCommand(options)}),events.command("timeline <entity-id>").description("Event timeline for a task, agent, wish, traceId, or session_id (default: last 24h)").option("--json","Output as JSON").option("--limit <n>","Max rows to return (default 200, hard cap 2000)").option("--since <duration>",'Time window \u2014 e.g. 10m, 24h, 7d, or "all" for full history. Default: 24h. '+'"all" reverts to the unbounded scan and may time out on production-sized audit logs.').action(async(entityId,options)=>{await eventsTimelineCommand(entityId,options)}),events.command("summary").description("High-level stats: agents spawned, tasks moved, costs, errors").option("--today","Show summary for the last 24h").option("--since <duration>","Time window (e.g., 1h, 7d)","24h").option("--json","Output as JSON").action(async(options)=>{await eventsSummaryCommand(options)}),events.command("scan").description("Full server cost scan via ccusage (all CC sessions, not just genie-spawned)").option("--since <date>","Start date in YYYYMMDD format").option("--json","Output as JSON").option("--breakdown","Show per-model breakdown").action(async(options)=>{await eventsScanCommand(options)}),events.command("subscribe").description("Mint a signed subscription token for genie events stream --follow").requiredOption("--role <role>","RBAC role: events:admin|events:operator|events:subscriber|events:audit").option("--types <csv>","Comma-separated allowed event types (subset of role defaults)").option("--channels <csv>","Comma-separated allowed LISTEN channels (subset of role defaults)").option("--ttl <duration>","Token time-to-live (e.g., 30m, 1h, 24h). Defaults to 1h.").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--subscriber-id <id>","Stable id for the subscriber agent").option("--json","Output as JSON").action(async(options)=>{await subscribeCommand(options)});let admin=events.command("admin").description("Incident-response admin commands (sentinel H6 audited)");admin.command("revoke-subscriber").description("Add a subscription token to the revocation list").requiredOption("--token-id <id>","Token id from `genie events subscribe` output").option("--subscriber-id <id>","Subscriber id associated with the token").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--reason <text>","IR justification for revocation").option("--json","Output as JSON").action(async(options)=>{await revokeSubscriberCommand(options)}),admin.command("rotate-redaction-keys").description("Rotate redaction + audit HMAC keys, preserving prior versions for lookup").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--new-key <material>","Explicit key material (default: 32 bytes hex from /dev/urandom)").option("--target <scope>","redaction|audit|both (default: both)").option("--json","Output as JSON").action(async(options)=>{await rotateRedactionKeysCommand(options)}),admin.command("un-hash").description("Admin reverse-lookup for a Tier-A hash (emits audit.un_hash)").requiredOption("--namespace <ns>","Hash namespace (e.g., agent, actor, session)").requiredOption("--hashed-value <hash>","Tier-A hash tag to reverse").option("--candidates <csv>","Comma-separated candidate plaintexts to brute-force").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--reason <text>","IR justification (appears in audit.un_hash)").option("--ticket <ref>","Incident ticket reference").option("--json","Output as JSON").action(async(options)=>{await unHashCommand(options)}),admin.command("export-audit").description("Produce a signed audit-chain bundle (emits audit.export)").option("--signed","Require GENIE_AUDIT_EXPORT_SECRET for HMAC signing",!0).option("--since <duration>","Advisory time window (authoritative cursor is --since-id)").option("--since-id <n>","Authoritative id cursor to resume from").option("--limit <n>","Max rows to include").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--output <path>","Write bundle to file; omit to print to stdout").option("--reason <text>","IR justification (appears in audit.export)").option("--json","Output as JSON").action(async(options)=>{await exportAuditCommand(options)}),admin.command("verify-chain").description("Quick chain-integrity check (no export)").option("--since-id <n>","Start id","0").option("--limit <n>","Max rows to verify").option("--json","Output as JSON").action(async(options)=>{await verifyChainCommand(options)}),admin.command("list-revocations").description("List revoked token ids for a tenant").option("--tenant <id>",'Tenant id. Defaults to "default".').option("--json","Output as JSON").action(async(options)=>{await listRevocationsCommand(options)})}init_genie_tokens();init_term_format();import{execSync as execSync11}from"child_process";import{existsSync as existsSync55,mkdirSync as mkdirSync25,readFileSync as readFileSync37,writeFileSync as writeFileSync24}from"fs";import{dirname as dirname24,join as join67}from"path";var _boardService;async function getBoardService(){if(!_boardService)_boardService=await Promise.resolve().then(() => (init_board_service(),exports_board_service));return _boardService}var _taskService3;async function getTaskService3(){if(!_taskService3)_taskService3=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService3}var _templateService;async function getTemplateService(){if(!_templateService)_templateService=await Promise.resolve().then(() => (init_template_service(),exports_template_service));return _templateService}async function resolveProjectId(name){let project=await(await getTaskService3()).getProjectByName(name);if(!project)throw Error(`Project not found: ${name}`);return project.id}async function resolveBoard(name,projectName){let bs=await getBoardService(),projectId;if(projectName)projectId=await resolveProjectId(projectName);let board=await bs.getBoard(name,projectId);if(!board)throw Error(`Board not found: ${name}`);return board}function printBoardTable(boards,projectMap){console.log(` ${padRight("NAME",24)} ${padRight("PROJECT",20)} ${padRight("COLUMNS",10)} CREATED`),console.log(` ${"\u2500".repeat(70)}`);for(let b2 of boards){let projName=b2.projectId?projectMap.get(b2.projectId)??b2.projectId:"-",colCount=String(b2.columns.length),created=formatDate(b2.createdAt);console.log(` ${padRight(truncate2(b2.name,22),24)} ${padRight(truncate2(projName,18),20)} ${padRight(colCount,10)} ${created}`)}console.log(`
4287
4290
  ${boards.length} board${boards.length===1?"":"s"}`)}function printColumnPipeline(columns,header){console.log(`
4288
4291
  ${header}`),console.log("\u2500".repeat(60));let sorted=[...columns].sort((a,b2)=>a.position-b2.position);for(let i2=0;i2<sorted.length;i2++){let c=sorted[i2],arrow=i2<sorted.length-1?" \u2192":"",gate=` [gate: ${c.gate}]`,action=c.action?` (action: ${c.action})`:"";console.log(` ${i2+1}. ${c.label??c.name}${gate}${action}${arrow}`)}console.log("")}function printTemplateTable(templates){console.log(` ${padRight("NAME",24)} ${padRight("COLUMNS",10)} ${padRight("BUILTIN",10)} DESCRIPTION`),console.log(` ${"\u2500".repeat(80)}`);for(let t of templates){let colCount=String(t.columns.length),builtin=t.isBuiltin?"yes":"no",desc=t.description?truncate2(t.description,30):"-";console.log(` ${padRight(truncate2(t.name,22),24)} ${padRight(colCount,10)} ${padRight(builtin,10)} ${desc}`)}console.log(`
4289
4292
  ${templates.length} template${templates.length===1?"":"s"}`)}async function handleBoardCreate(name,options){let bs=await getBoardService(),tmpl=await getTemplateService(),projectId;if(options.project)projectId=await resolveProjectId(options.project);let columns;if(options.from){let template=await tmpl.getTemplate(options.from);if(!template)throw Error(`Template not found: ${options.from}`);columns=template.columns}else if(options.columns)columns=options.columns.split(",").map((colName,i2)=>({name:colName.trim(),label:colName.trim(),gate:"human",position:i2}));let board=await bs.createBoard({name,projectId,description:options.description,columns});console.log(`Created board "${board.name}" (${board.id}) with ${board.columns.length} columns`)}async function handleBoardList(options){let bs=await getBoardService(),ts3=await getTaskService3(),projectId;if(options.project)projectId=await resolveProjectId(options.project);let boards=await bs.listBoards(projectId,options.all);if(options.json){console.log(JSON.stringify(boards,null,2));return}let projects=await ts3.listProjects(),projectMap=new Map;for(let p of projects)projectMap.set(p.id,p.name);printBoardTable(boards,projectMap)}async function handleBoardShow(name,options){let ts3=await getTaskService3(),board=await resolveBoard(name,options.project);if(options.json){console.log(JSON.stringify(board,null,2));return}let projectName="-";if(board.projectId){let proj=(await ts3.listProjects()).find((p)=>p.id===board.projectId);if(proj)projectName=proj.name}if(console.log(`
4290
4293
  Board: ${board.name} (${board.id})`),board.description)console.log(`Description: ${board.description}`);console.log(`Project: ${projectName}`),console.log(`Columns: ${board.columns.length}`),console.log("\u2500".repeat(60));let tasks=await ts3.listTasks({boardId:board.id,allProjects:!0}),countByColumn=new Map;for(let t of tasks){let colId=t.stage;countByColumn.set(colId,(countByColumn.get(colId)??0)+1)}let sorted=[...board.columns].sort((a,b2)=>a.position-b2.position);console.log(`
4291
4294
  Columns:`);for(let i2=0;i2<sorted.length;i2++){let c=sorted[i2],count=countByColumn.get(c.name)??countByColumn.get(c.id)??0,gate=` [gate: ${c.gate}]`,action=c.action?` (action: ${c.action})`:"";console.log(` ${i2+1}. ${c.label??c.name}${gate}${action} \u2014 ${count} task${count===1?"":"s"}`)}console.log("")}function buildColumnUpdates(options){let updates={};if(options.gate)updates.gate=options.gate;if(options.action)updates.action=options.action;if(options.color)updates.color=options.color;if(options.rename)updates.name=options.rename,updates.label=options.rename;return updates}async function handleBoardEdit(name,options){let bs=await getBoardService(),board=await resolveBoard(name,options.project);if(options.column){let col=board.columns.find((c)=>c.name===options.column||c.label===options.column);if(!col)throw Error(`Column not found: ${options.column}`);let updates=buildColumnUpdates(options);if(!await bs.updateColumn(board.id,col.id,updates))throw Error(`Failed to update column: ${options.column}`);console.log(`Updated column "${options.column}" on board "${board.name}".`);return}let boardUpdates={};if(options.name)boardUpdates.name=options.name;if(options.description)boardUpdates.description=options.description;if(Object.keys(boardUpdates).length===0)console.error("Error: No updates specified. Use --column, --name, or --description."),process.exit(1);let updated=await bs.updateBoard(board.id,boardUpdates);if(!updated)throw Error(`Failed to update board: ${name}`);console.log(`Updated board "${updated.name}" (${updated.id}).`)}async function handleBoardDelete(name,options){let bs=await getBoardService(),board=await resolveBoard(name,options.project);if(!options.force)console.log(`Deleting board "${board.name}" (${board.id})...`);if(!await bs.deleteBoard(board.id))throw Error(`Failed to delete board: ${name}`);console.log(`Deleted board "${board.name}" (${board.id}).`)}async function handleBoardColumns(name,options){let board=await resolveBoard(name,options.project);if(options.json){console.log(JSON.stringify(board.columns,null,2));return}printColumnPipeline(board.columns,`Board: ${board.name} (${board.columns.length} columns)`)}async function handleBoardUse(name,options){let board=await resolveBoard(name,options.project),repoRoot=execSync11("git rev-parse --show-toplevel",{encoding:"utf-8"}).trim(),genieDir=join67(repoRoot,".genie"),configPath2=join67(genieDir,"config.json");if(!existsSync55(genieDir))mkdirSync25(genieDir,{recursive:!0});let config={};if(existsSync55(configPath2))try{config=JSON.parse(readFileSync37(configPath2,"utf-8"))}catch{}config.activeBoard=board.id,writeFileSync24(configPath2,`${JSON.stringify(config,null,2)}
4292
- `),console.log(`Active board set to "${board.name}" (${board.id})`)}async function handleBoardExport(name,options){let bs=await getBoardService(),board=await resolveBoard(name,options.project),exported=await bs.exportBoard(board.id),json2=JSON.stringify(exported,null,2);if(options.output){let dir=dirname23(options.output);if(!existsSync55(dir))mkdirSync25(dir,{recursive:!0});writeFileSync24(options.output,`${json2}
4295
+ `),console.log(`Active board set to "${board.name}" (${board.id})`)}async function handleBoardExport(name,options){let bs=await getBoardService(),board=await resolveBoard(name,options.project),exported=await bs.exportBoard(board.id),json2=JSON.stringify(exported,null,2);if(options.output){let dir=dirname24(options.output);if(!existsSync55(dir))mkdirSync25(dir,{recursive:!0});writeFileSync24(options.output,`${json2}
4293
4296
  `),console.log(`Exported board "${board.name}" to ${options.output}`)}else console.log(json2)}async function handleBoardReconcile(name,options){let{reconcileBoard:reconcileBoard2}=await Promise.resolve().then(() => (init_board_service(),exports_board_service)),board=await resolveBoard(name,options.project),result2=await reconcileBoard2(board.id);if(options.json){console.log(JSON.stringify(result2,null,2));return}if(result2.fixed===0&&result2.orphaned===0){console.log(`Board "${board.name}": all tasks have valid column_ids.`);return}if(console.log(`Board "${board.name}" reconciliation:`),console.log(` Fixed: ${result2.fixed} task${result2.fixed===1?"":"s"}`),result2.orphaned>0){let count=result2.orphaned;console.log(` Still orphaned: ${count} task${count===1?"":"s"} (stage doesn't match any column)`)}}async function handleBoardImport(options){let bs=await getBoardService(),projectId=await resolveProjectId(options.project),raw=readFileSync37(options.json,"utf-8"),data=JSON.parse(raw),board=await bs.importBoard(data,projectId);console.log(`Imported board "${board.name}" (${board.id}) with ${board.columns.length} columns`)}async function handleTemplateList(options){let templates=await(await getTemplateService()).listTemplates();if(options.json){console.log(JSON.stringify(templates,null,2));return}printTemplateTable(templates)}async function handleTemplateShow(name,options){let template=await(await getTemplateService()).getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(options.json){console.log(JSON.stringify(template,null,2));return}if(console.log(`
4294
- Template: ${template.name} (${template.id})`),template.description)console.log(`Description: ${template.description}`);if(template.icon)console.log(`Icon: ${template.icon}`);console.log(`Built-in: ${template.isBuiltin?"yes":"no"}`),printColumnPipeline(template.columns,`Pipeline (${template.columns.length} columns)`)}async function handleTemplateCreate(name,options){let tmpl=await getTemplateService();if(options.fromBoard){let board=await(await getBoardService()).getBoard(options.fromBoard);if(!board)throw Error(`Board not found: ${options.fromBoard}`);let template2=await tmpl.snapshotFromBoard(board.id,name);console.log(`Created template "${template2.name}" (${template2.id}) from board "${board.name}" with ${template2.columns.length} columns`);return}let columns;if(options.columns)columns=options.columns.split(",").map((colName,i2)=>({id:crypto.randomUUID(),name:colName.trim(),label:colName.trim(),gate:"human",action:null,auto_advance:!1,transitions:[],roles:["*"],color:palette.textDim,parallel:!1,on_fail:null,position:i2}));let template=await tmpl.createTemplate({name,description:options.description,columns});console.log(`Created template "${template.name}" (${template.id}) with ${template.columns.length} columns`)}async function handleTemplateEdit(name,options){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!options.column)console.error("Error: --column is required for template edit."),process.exit(1);let updates={};if(options.gate)updates.gate=options.gate;if(options.action)updates.action=options.action;if(options.color)updates.color=options.color;if(options.rename)updates.name=options.rename,updates.label=options.rename;if(!await tmpl.updateTemplateColumn(template.id,options.column,updates))throw Error(`Failed to update template: ${name}`);console.log(`Updated column "${options.column}" on template "${template.name}".`)}async function handleTemplateRename(oldName,newName){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(oldName);if(!template)throw Error(`Template not found: ${oldName}`);let updated=await tmpl.renameTemplate(template.id,newName);if(!updated)throw Error(`Failed to rename template: ${oldName}`);console.log(`Renamed template "${oldName}" to "${updated.name}".`)}async function handleTemplateDelete(name){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!await tmpl.deleteTemplate(template.id))throw Error(`Failed to delete template: ${name}`);console.log(`Deleted template "${template.name}" (${template.id}).`)}function registerBoardCommands(program2){let board=program2.command("board").description("Board and pipeline management");board.command("create <name>").description("Create a new board").option("--project <project>","Project name").option("--from <template>","Create from template name").option("--columns <columns>","Comma-separated column names").option("--description <text>","Board description").action(async(name,options)=>{try{await handleBoardCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("list").description("List all boards").option("--project <project>","Filter by project").option("--all","Include archived boards").option("--json","Output as JSON").action(async(options)=>{try{await handleBoardList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("show <name...>").description("Show board detail").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardShow(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("edit <name...>").description("Edit board or column properties").option("--project <project>","Disambiguate by project").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--color <color>","New color hex").option("--rename <new>","Rename the column").option("--name <new>","Rename the board itself").option("--description <text>","Update description").action(async(nameParts,options)=>{try{await handleBoardEdit(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("delete <name...>").description("Delete a board").option("--project <project>","Disambiguate by project").option("--force","Skip confirmation").action(async(nameParts,options)=>{try{await handleBoardDelete(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("columns <name...>").description("Show board column pipeline").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardColumns(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("use <name...>").description("Set active board for current repo").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{await handleBoardUse(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("export <name...>").description("Export board as JSON").option("--project <project>","Disambiguate by project").option("--output <file>","Write to file instead of stdout").option("--json","Output as JSON (default, accepted for consistency)").action(async(nameParts,options)=>{try{await handleBoardExport(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("reconcile <name...>").description("Fix orphaned column_ids by matching task stage to board columns").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardReconcile(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("archive <name...>").description("Archive a board and its unfinished tasks").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{let ts3=await getTaskService3(),board2=await resolveBoard(nameParts.join(" "),options.project);await ts3.archiveBoard(board2.id),console.log(`Archived board "${board2.name}" and its unfinished tasks.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("import").description("Import board from JSON file").requiredOption("--json <file>","JSON file to import").requiredOption("--project <project>","Target project").action(async(options)=>{try{await handleBoardImport(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}});let template=board.command("template").description("Board template management");template.command("list").description("List all board templates").option("--json","Output as JSON").action(async(options)=>{try{await handleTemplateList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("show <name>").description("Show template detail with pipeline view").option("--json","Output as JSON").action(async(name,options)=>{try{await handleTemplateShow(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("create <name>").description("Create a board template").option("--from-board <board>","Create from existing board").option("--columns <columns>","Comma-separated column names").option("--description <text>","Template description").action(async(name,options)=>{try{await handleTemplateCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("edit <name>").description("Edit a template column").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--rename <new>","Rename the column").option("--color <color>","New color hex").action(async(name,options)=>{try{await handleTemplateEdit(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("rename <old> <new>").description("Rename a template").action(async(oldName,newName)=>{try{await handleTemplateRename(oldName,newName)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("delete <name>").description("Delete a template").action(async(name)=>{try{await handleTemplateDelete(name)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_brain_vaults();import{execSync as execSync12}from"child_process";import{existsSync as existsSync56,mkdirSync as mkdirSync26,readFileSync as readFileSync38,realpathSync as realpathSync7,writeFileSync as writeFileSync25}from"fs";import{homedir as homedir45}from"os";import{dirname as dirname24,join as join68,resolve as resolve13}from"path";var BRAIN_PKG2="@khal-os/brain",BRAIN_REPO="khal-os/brain";function resolveGenieRoot(){try{let scriptDir=dirname24(realpathSync7(process.argv[1])),candidates=[resolve13(scriptDir,".."),resolve13(scriptDir,"..","..")];for(let c of candidates)if(existsSync56(join68(c,"package.json")))return c}catch{}return resolve13(import.meta.dir,"..","..")}var BRAIN_DIR2=join68(resolveGenieRoot(),"node_modules","@khal-os","brain"),CACHE_PATH=join68(homedir45(),".genie","brain-version-check.json");function compareVersions2(a,b2){let partsA=a.split(".").map(Number),partsB=b2.split(".").map(Number);for(let i2=0;i2<Math.max(partsA.length,partsB.length);i2++){let diff=(partsA[i2]??0)-(partsB[i2]??0);if(diff!==0)return diff}return 0}function readLocalBrainVersion(){try{return JSON.parse(readFileSync38(join68(BRAIN_DIR2,"package.json"),"utf-8")).version??"unknown"}catch{return}}function resolveBrainBin(){let candidates=[join68(resolveGenieRoot(),"node_modules",".bin","brain"),join68(BRAIN_DIR2,"dist","cli.js")];for(let c of candidates)if(existsSync56(c))return c;return}function readActiveBrainConfig(){try{let configPath2=join68(homedir45(),".brain","config.json");if(!existsSync56(configPath2))return null;let data=JSON.parse(readFileSync38(configPath2,"utf-8"));if(!data.pid)return null;return{pid:data.pid,pgPort:data.pgPort,brainPath:data.brainPath}}catch{return null}}function isProcessAlive2(pid){try{return process.kill(pid,0),!0}catch{return!1}}async function stopBrainDaemon(){let config=readActiveBrainConfig();if(!config?.pid||!isProcessAlive2(config.pid))return!1;let brainBin=resolveBrainBin(),brainPath=config.brainPath;if(brainBin)try{let pathArg=brainPath?` --brain-path "${brainPath}"`:"";execSync12(`"${brainBin}" serve stop${pathArg}`,{stdio:"pipe",timeout:1e4})}catch{}for(let i2=0;i2<25;i2++){if(!isProcessAlive2(config.pid))return!0;await new Promise((r)=>setTimeout(r,200))}try{process.kill(config.pid,"SIGKILL")}catch{}return!0}function startBrainDaemon(vaultPath,extraArgs){let bin=resolveBrainBin();if(!bin)return;try{let argsStr=extraArgs?.length?` ${extraArgs.join(" ")}`:"";execSync12(`"${bin}" serve --daemon --brain-path "${vaultPath}"${argsStr}`,{stdio:"inherit",timeout:15000}),console.log(" Brain daemon started.")}catch{console.log(" Daemon failed to start. Run: brain serve --daemon")}}function readSavedDaemonArgs(brainPath){try{let serverJsonPath=join68(brainPath,".brain-server.json");return JSON.parse(readFileSync38(serverJsonPath,"utf-8")).args}catch{return}}function checkForUpdates(cachePath){try{let p=cachePath??CACHE_PATH;if(!existsSync56(p))return{updateAvailable:!1};let cache=JSON.parse(readFileSync38(p,"utf-8"));if(cache.updateAvailable&&cache.latestVersion)return{updateAvailable:!0,latestVersion:cache.latestVersion};return{updateAvailable:!1}}catch{return{updateAvailable:!1}}}function refreshVersionCache(localVersion){try{let version=localVersion??readLocalBrainVersion();if(!version)return;let latestTag=execSync12(`gh release view --repo ${BRAIN_REPO} --json tagName -q .tagName`,{stdio:"pipe",encoding:"utf-8"}).trim(),latestVersion=latestTag.replace(/^v/,""),localCore=version.replace(/^\d+\./,""),latestCore=latestVersion.replace(/^\d+\./,""),updateAvailable=compareVersions2(latestCore,localCore)>0,cacheDir=join68(homedir45(),".genie");mkdirSync26(cacheDir,{recursive:!0}),writeFileSync25(CACHE_PATH,JSON.stringify({checkedAt:new Date().toISOString(),localVersion:version,latestTag,latestVersion,updateAvailable},null,2))}catch{}}async function updateBrain(){if(!existsSync56(join68(BRAIN_DIR2,"package.json")))return console.log(" Brain is not installed. Run: genie brain install"),!1;let oldVersion=readLocalBrainVersion()??"unknown";console.log(" Checking for updates...");let tag;try{tag=execSync12(`gh release view --repo ${BRAIN_REPO} --json tagName -q .tagName`,{stdio:"pipe",encoding:"utf-8"}).trim()}catch{return console.error(" Failed to check latest release. Ensure: gh auth login"),!1}let newVersion=tag.replace(/^v/,"");if(compareVersions2(newVersion,oldVersion)<=0)return console.log(` Already at latest version (${oldVersion}).`),!0;console.log(` Upgrading: ${oldVersion} \u2192 ${newVersion}`),console.log("");let activeConfig=readActiveBrainConfig(),savedArgs=activeConfig?.brainPath?readSavedDaemonArgs(activeConfig.brainPath):void 0,wasRunning=activeConfig?await stopBrainDaemon():!1,tmpDir=join68(homedir45(),".cache","genie-brain");mkdirSync26(tmpDir,{recursive:!0}),execSync12(`gh release download ${tag} --repo ${BRAIN_REPO} --pattern '*.tgz' --dir "${tmpDir}" --clobber`,{stdio:"inherit"}),execSync12(`rm -rf "${BRAIN_DIR2}"`,{stdio:"pipe"}),mkdirSync26(BRAIN_DIR2,{recursive:!0}),execSync12(`tar xzf "${tmpDir}/khal-os-brain-${newVersion}.tgz" -C "${BRAIN_DIR2}" --strip-components=1`,{stdio:"inherit"}),execSync12("bun install",{cwd:BRAIN_DIR2,stdio:"inherit"}),console.log(`
4297
+ Template: ${template.name} (${template.id})`),template.description)console.log(`Description: ${template.description}`);if(template.icon)console.log(`Icon: ${template.icon}`);console.log(`Built-in: ${template.isBuiltin?"yes":"no"}`),printColumnPipeline(template.columns,`Pipeline (${template.columns.length} columns)`)}async function handleTemplateCreate(name,options){let tmpl=await getTemplateService();if(options.fromBoard){let board=await(await getBoardService()).getBoard(options.fromBoard);if(!board)throw Error(`Board not found: ${options.fromBoard}`);let template2=await tmpl.snapshotFromBoard(board.id,name);console.log(`Created template "${template2.name}" (${template2.id}) from board "${board.name}" with ${template2.columns.length} columns`);return}let columns;if(options.columns)columns=options.columns.split(",").map((colName,i2)=>({id:crypto.randomUUID(),name:colName.trim(),label:colName.trim(),gate:"human",action:null,auto_advance:!1,transitions:[],roles:["*"],color:palette.textDim,parallel:!1,on_fail:null,position:i2}));let template=await tmpl.createTemplate({name,description:options.description,columns});console.log(`Created template "${template.name}" (${template.id}) with ${template.columns.length} columns`)}async function handleTemplateEdit(name,options){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!options.column)console.error("Error: --column is required for template edit."),process.exit(1);let updates={};if(options.gate)updates.gate=options.gate;if(options.action)updates.action=options.action;if(options.color)updates.color=options.color;if(options.rename)updates.name=options.rename,updates.label=options.rename;if(!await tmpl.updateTemplateColumn(template.id,options.column,updates))throw Error(`Failed to update template: ${name}`);console.log(`Updated column "${options.column}" on template "${template.name}".`)}async function handleTemplateRename(oldName,newName){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(oldName);if(!template)throw Error(`Template not found: ${oldName}`);let updated=await tmpl.renameTemplate(template.id,newName);if(!updated)throw Error(`Failed to rename template: ${oldName}`);console.log(`Renamed template "${oldName}" to "${updated.name}".`)}async function handleTemplateDelete(name){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!await tmpl.deleteTemplate(template.id))throw Error(`Failed to delete template: ${name}`);console.log(`Deleted template "${template.name}" (${template.id}).`)}function registerBoardCommands(program2){let board=program2.command("board").description("Board and pipeline management");board.command("create <name>").description("Create a new board").option("--project <project>","Project name").option("--from <template>","Create from template name").option("--columns <columns>","Comma-separated column names").option("--description <text>","Board description").action(async(name,options)=>{try{await handleBoardCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("list").description("List all boards").option("--project <project>","Filter by project").option("--all","Include archived boards").option("--json","Output as JSON").action(async(options)=>{try{await handleBoardList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("show <name...>").description("Show board detail").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardShow(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("edit <name...>").description("Edit board or column properties").option("--project <project>","Disambiguate by project").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--color <color>","New color hex").option("--rename <new>","Rename the column").option("--name <new>","Rename the board itself").option("--description <text>","Update description").action(async(nameParts,options)=>{try{await handleBoardEdit(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("delete <name...>").description("Delete a board").option("--project <project>","Disambiguate by project").option("--force","Skip confirmation").action(async(nameParts,options)=>{try{await handleBoardDelete(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("columns <name...>").description("Show board column pipeline").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardColumns(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("use <name...>").description("Set active board for current repo").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{await handleBoardUse(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("export <name...>").description("Export board as JSON").option("--project <project>","Disambiguate by project").option("--output <file>","Write to file instead of stdout").option("--json","Output as JSON (default, accepted for consistency)").action(async(nameParts,options)=>{try{await handleBoardExport(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("reconcile <name...>").description("Fix orphaned column_ids by matching task stage to board columns").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardReconcile(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("archive <name...>").description("Archive a board and its unfinished tasks").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{let ts3=await getTaskService3(),board2=await resolveBoard(nameParts.join(" "),options.project);await ts3.archiveBoard(board2.id),console.log(`Archived board "${board2.name}" and its unfinished tasks.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("import").description("Import board from JSON file").requiredOption("--json <file>","JSON file to import").requiredOption("--project <project>","Target project").action(async(options)=>{try{await handleBoardImport(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}});let template=board.command("template").description("Board template management");template.command("list").description("List all board templates").option("--json","Output as JSON").action(async(options)=>{try{await handleTemplateList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("show <name>").description("Show template detail with pipeline view").option("--json","Output as JSON").action(async(name,options)=>{try{await handleTemplateShow(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("create <name>").description("Create a board template").option("--from-board <board>","Create from existing board").option("--columns <columns>","Comma-separated column names").option("--description <text>","Template description").action(async(name,options)=>{try{await handleTemplateCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("edit <name>").description("Edit a template column").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--rename <new>","Rename the column").option("--color <color>","New color hex").action(async(name,options)=>{try{await handleTemplateEdit(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("rename <old> <new>").description("Rename a template").action(async(oldName,newName)=>{try{await handleTemplateRename(oldName,newName)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("delete <name>").description("Delete a template").action(async(name)=>{try{await handleTemplateDelete(name)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_brain_vaults();import{execSync as execSync12}from"child_process";import{existsSync as existsSync56,mkdirSync as mkdirSync26,readFileSync as readFileSync38,realpathSync as realpathSync8,writeFileSync as writeFileSync25}from"fs";import{homedir as homedir45}from"os";import{dirname as dirname25,join as join68,resolve as resolve13}from"path";var BRAIN_PKG2="@khal-os/brain",BRAIN_REPO="khal-os/brain";function resolveGenieRoot(){try{let scriptDir=dirname25(realpathSync8(process.argv[1])),candidates=[resolve13(scriptDir,".."),resolve13(scriptDir,"..","..")];for(let c of candidates)if(existsSync56(join68(c,"package.json")))return c}catch{}return resolve13(import.meta.dir,"..","..")}var BRAIN_DIR2=join68(resolveGenieRoot(),"node_modules","@khal-os","brain"),CACHE_PATH=join68(homedir45(),".genie","brain-version-check.json");function compareVersions2(a,b2){let partsA=a.split(".").map(Number),partsB=b2.split(".").map(Number);for(let i2=0;i2<Math.max(partsA.length,partsB.length);i2++){let diff=(partsA[i2]??0)-(partsB[i2]??0);if(diff!==0)return diff}return 0}function readLocalBrainVersion(){try{return JSON.parse(readFileSync38(join68(BRAIN_DIR2,"package.json"),"utf-8")).version??"unknown"}catch{return}}function resolveBrainBin(){let candidates=[join68(resolveGenieRoot(),"node_modules",".bin","brain"),join68(BRAIN_DIR2,"dist","cli.js")];for(let c of candidates)if(existsSync56(c))return c;return}function readActiveBrainConfig(){try{let configPath2=join68(homedir45(),".brain","config.json");if(!existsSync56(configPath2))return null;let data=JSON.parse(readFileSync38(configPath2,"utf-8"));if(!data.pid)return null;return{pid:data.pid,pgPort:data.pgPort,brainPath:data.brainPath}}catch{return null}}function isProcessAlive2(pid){try{return process.kill(pid,0),!0}catch{return!1}}async function stopBrainDaemon(){let config=readActiveBrainConfig();if(!config?.pid||!isProcessAlive2(config.pid))return!1;let brainBin=resolveBrainBin(),brainPath=config.brainPath;if(brainBin)try{let pathArg=brainPath?` --brain-path "${brainPath}"`:"";execSync12(`"${brainBin}" serve stop${pathArg}`,{stdio:"pipe",timeout:1e4})}catch{}for(let i2=0;i2<25;i2++){if(!isProcessAlive2(config.pid))return!0;await new Promise((r)=>setTimeout(r,200))}try{process.kill(config.pid,"SIGKILL")}catch{}return!0}function startBrainDaemon(vaultPath,extraArgs){let bin=resolveBrainBin();if(!bin)return;try{let argsStr=extraArgs?.length?` ${extraArgs.join(" ")}`:"";execSync12(`"${bin}" serve --daemon --brain-path "${vaultPath}"${argsStr}`,{stdio:"inherit",timeout:15000}),console.log(" Brain daemon started.")}catch{console.log(" Daemon failed to start. Run: brain serve --daemon")}}function readSavedDaemonArgs(brainPath){try{let serverJsonPath=join68(brainPath,".brain-server.json");return JSON.parse(readFileSync38(serverJsonPath,"utf-8")).args}catch{return}}function checkForUpdates(cachePath){try{let p=cachePath??CACHE_PATH;if(!existsSync56(p))return{updateAvailable:!1};let cache=JSON.parse(readFileSync38(p,"utf-8"));if(cache.updateAvailable&&cache.latestVersion)return{updateAvailable:!0,latestVersion:cache.latestVersion};return{updateAvailable:!1}}catch{return{updateAvailable:!1}}}function refreshVersionCache(localVersion){try{let version=localVersion??readLocalBrainVersion();if(!version)return;let latestTag=execSync12(`gh release view --repo ${BRAIN_REPO} --json tagName -q .tagName`,{stdio:"pipe",encoding:"utf-8"}).trim(),latestVersion=latestTag.replace(/^v/,""),localCore=version.replace(/^\d+\./,""),latestCore=latestVersion.replace(/^\d+\./,""),updateAvailable=compareVersions2(latestCore,localCore)>0,cacheDir=join68(homedir45(),".genie");mkdirSync26(cacheDir,{recursive:!0}),writeFileSync25(CACHE_PATH,JSON.stringify({checkedAt:new Date().toISOString(),localVersion:version,latestTag,latestVersion,updateAvailable},null,2))}catch{}}async function updateBrain(){if(!existsSync56(join68(BRAIN_DIR2,"package.json")))return console.log(" Brain is not installed. Run: genie brain install"),!1;let oldVersion=readLocalBrainVersion()??"unknown";console.log(" Checking for updates...");let tag;try{tag=execSync12(`gh release view --repo ${BRAIN_REPO} --json tagName -q .tagName`,{stdio:"pipe",encoding:"utf-8"}).trim()}catch{return console.error(" Failed to check latest release. Ensure: gh auth login"),!1}let newVersion=tag.replace(/^v/,"");if(compareVersions2(newVersion,oldVersion)<=0)return console.log(` Already at latest version (${oldVersion}).`),!0;console.log(` Upgrading: ${oldVersion} \u2192 ${newVersion}`),console.log("");let activeConfig=readActiveBrainConfig(),savedArgs=activeConfig?.brainPath?readSavedDaemonArgs(activeConfig.brainPath):void 0,wasRunning=activeConfig?await stopBrainDaemon():!1,tmpDir=join68(homedir45(),".cache","genie-brain");mkdirSync26(tmpDir,{recursive:!0}),execSync12(`gh release download ${tag} --repo ${BRAIN_REPO} --pattern '*.tgz' --dir "${tmpDir}" --clobber`,{stdio:"inherit"}),execSync12(`rm -rf "${BRAIN_DIR2}"`,{stdio:"pipe"}),mkdirSync26(BRAIN_DIR2,{recursive:!0}),execSync12(`tar xzf "${tmpDir}/khal-os-brain-${newVersion}.tgz" -C "${BRAIN_DIR2}" --strip-components=1`,{stdio:"inherit"}),execSync12("bun install",{cwd:BRAIN_DIR2,stdio:"inherit"}),console.log(`
4295
4298
  Updated: ${oldVersion} \u2192 ${newVersion}`);try{let migrateScript=`const b = require('${BRAIN_PKG2}'); if (b.runAllMigrations) b.runAllMigrations().then(() => process.exit(0)).catch((e) => { console.error(e); process.exit(1); }); else process.exit(0);`;execSync12(`bun -e "${migrateScript}"`,{cwd:BRAIN_DIR2,stdio:"inherit"}),console.log(" Migrations applied.")}catch{console.log(" Migration skipped. Run: genie brain migrate")}if(refreshVersionCache(newVersion),wasRunning&&activeConfig?.brainPath)startBrainDaemon(activeConfig.brainPath,savedArgs);return!0}async function showVersion(){let localVersion="not installed";try{let brain=await import(BRAIN_PKG2);localVersion=brain.getVersion?.()??brain.VERSION??"unknown"}catch(err){let msg=err instanceof Error?err.message:String(err);if(isModuleNotFound(msg)){console.log(" Brain is not installed. Run: genie brain install");return}}console.log(` Local: ${localVersion}`),refreshVersionCache(localVersion);let check2=checkForUpdates();if(check2.updateAvailable&&check2.latestVersion)console.log(` Latest: ${check2.latestVersion}`),console.log(""),console.log(" Update available. Run: genie brain upgrade");else console.log(" Status: up to date")}async function installBrain(){let{loadGenieConfigSync:loadGenieConfigSync2}=await Promise.resolve().then(() => (init_genie_config2(),exports_genie_config));if(!loadGenieConfigSync2().brain.embedded)return console.log(""),console.log(" Brain is configured as external (brain.embedded=false)."),console.log(" Genie will not install brain into its node_modules."),console.log(""),console.log(" Install brain standalone instead:"),console.log(" bun install -g @khal-os/brain@next # dev channel"),console.log(" bun install -g @khal-os/brain # stable channel"),console.log(""),console.log(" Then run your own brain serve:"),console.log(" brain serve --brain-path <path> [--port <port>]"),console.log(""),console.log(" To re-enable embedded management, remove brain.embedded from"),console.log(" ~/.genie/config.json (or set it to true)."),console.log(""),!0;console.log(""),console.log(" Installing brain from GitHub release (enterprise)..."),console.log(""),console.log(" Source: https://github.com/khal-os/brain"),console.log(" Requires: GitHub org membership (khal-os)"),console.log("");try{try{execSync12("gh auth token",{stdio:"pipe"})}catch{return console.error(" GitHub CLI not authenticated. Run: gh auth login"),!1}let tag=execSync12(`gh release view --repo ${BRAIN_REPO} --json tagName -q .tagName`,{stdio:"pipe",encoding:"utf-8"}).trim(),version=tag.replace(/^v/,"");console.log(` Latest release: ${tag}`),console.log("");let root=resolveGenieRoot(),brainDir=join68(root,"node_modules","@khal-os","brain"),tmpDir=join68(homedir45(),".cache","genie-brain");mkdirSync26(tmpDir,{recursive:!0}),execSync12(`gh release download ${tag} --repo ${BRAIN_REPO} --pattern '*.tgz' --dir "${tmpDir}" --clobber`,{stdio:"inherit"}),execSync12(`rm -rf "${brainDir}"`,{stdio:"pipe"}),mkdirSync26(brainDir,{recursive:!0}),execSync12(`tar xzf "${tmpDir}/khal-os-brain-${version}.tgz" -C "${brainDir}" --strip-components=1`,{stdio:"inherit"}),execSync12("bun install",{cwd:brainDir,stdio:"inherit"}),console.log(""),console.log(` Brain ${version} installed from GitHub release.`),console.log("");let installedBrain=null;try{let brain=await import(BRAIN_PKG2);if(installedBrain=brain,brain.runAllMigrations)console.log(" Running brain migrations..."),await brain.runAllMigrations(),console.log(" Brain tables created in Postgres.")}catch{console.log(" Auto-migration skipped. Run: genie brain migrate")}await runBrainInstallWizard();let vaultPath=await findBrainVault({brain:installedBrain});if(vaultPath)startBrainDaemon(vaultPath);else console.log(" No brain vault found. Create one with: brain init --name <name> --path <path>");return console.log(""),console.log(" Get started:"),console.log(" genie brain init --name my-brain --path ./brain"),console.log(""),!0}catch(err){let msg=err instanceof Error?err.message:String(err);if(msg.includes("Authentication")||msg.includes("permission")||msg.includes("404"))console.error(" Access denied. Brain is enterprise-only."),console.log(""),console.log(" You need:"),console.log(" 1. Membership in the khal-os GitHub org"),console.log(" 2. GitHub CLI authenticated: gh auth login"),console.log(""),console.log(" Manual install:"),console.log(` gh release download --repo ${BRAIN_REPO} --pattern '*.tgz'`),console.log(" tar xzf khal-os-brain-*.tgz -C node_modules/@khal-os/brain --strip-components=1"),console.log("");else console.error(` Install failed: ${msg}`),console.log(""),console.log(" Manual install:"),console.log(` gh release download --repo ${BRAIN_REPO} --pattern '*.tgz'`),console.log(" tar xzf khal-os-brain-*.tgz -C node_modules/@khal-os/brain --strip-components=1"),console.log("");return!1}}async function runBrainInstallWizard(){try{let brain=await import(BRAIN_PKG2);if(brain.execute)console.log(""),console.log(" Running brain install wizard (rlmx + smoke test)..."),await brain.execute(["install","--apply","--yes"])}catch(err){let msg=err instanceof Error?err.message:String(err);console.log(` Install wizard skipped (${msg.split(`
4296
4299
  `)[0]}). Run manually: brain install --apply --yes`)}}async function uninstallBrain(){try{if(!existsSync56(BRAIN_DIR2)){console.log(" Brain is not installed.");return}await stopBrainDaemon(),execSync12(`rm -rf "${BRAIN_DIR2}"`,{stdio:"pipe"}),console.log(" Brain uninstalled.")}catch{console.error(` Uninstall failed. Manual: rm -rf ${BRAIN_DIR2}`)}}function isModuleNotFound(msg){return msg.includes("Cannot find")||msg.includes("not found")||msg.includes("MODULE_NOT_FOUND")}function printNotInstalledMessage(){console.log(""),console.log(" Brain is an enterprise knowledge graph engine."),console.log(" It is not installed."),console.log(""),console.log(" Quick install:"),console.log(""),console.log(" genie brain install"),console.log(""),console.log(" Requires GitHub org membership (khal-os)."),console.log("")}async function executeBrainCommand(args){try{let brain=await import(BRAIN_PKG2);if(brain.execute){await brain.execute(args);let check2=checkForUpdates();if(check2.updateAvailable&&check2.latestVersion)console.log(`
4297
4300
  Update available (${check2.latestVersion}). Run: genie brain upgrade`)}else console.error("Brain module loaded but execute() not found."),console.error("Update: genie brain install"),process.exit(1)}catch(err){let msg=err instanceof Error?err.message:String(err);if(isModuleNotFound(msg))printNotInstalledMessage(),process.exit(1);else console.error(`Brain error: ${msg}`),process.exit(1)}}function registerBrainCommands(program2){let brain=program2.command("brain").description("Knowledge graph engine (enterprise) \u2014 forwards unknown subcommands to @khal-os/brain").allowUnknownOption().allowExcessArguments().action(async(_options,cmd)=>{let args=cmd.args;if(args.length===0){brain.help();return}await executeBrainCommand(args)}).addHelpText("after",`
@@ -4352,7 +4355,7 @@ Genie Scheduler Daemon`),console.log("\u2500".repeat(50)),console.log(` Status:
4352
4355
  (showing last ${lines} of ${allLines.length} entries)`)}async function tailFollow(filePath,initialLines){let{watch:watch2}=await import("fs");tailStatic(filePath,initialLines),console.log(`
4353
4356
  --- following (Ctrl+C to exit) ---
4354
4357
  `);let lastSize=existsSync57(filePath)?readFileSync39(filePath).length:0,watcher2=watch2(filePath,()=>{try{let content=readFileSync39(filePath,"utf-8");if(content.length>lastSize){let newLines=content.slice(lastSize).trim().split(`
4355
- `).filter(Boolean);for(let line of newLines)printLogLine(line);lastSize=content.length}}catch{}});process.on("SIGINT",()=>{watcher2.close(),process.exit(0)}),await new Promise(()=>{})}function printLogLine(raw){try{let entry2=JSON.parse(raw),ts3=entry2.timestamp?new Date(entry2.timestamp).toLocaleTimeString("en-US",{hour12:!1}):"??:??:??",level=(entry2.level??"info").toUpperCase().padEnd(5),event=entry2.event??"unknown",extras=Object.entries(entry2).filter(([k])=>!["timestamp","level","event"].includes(k)).map(([k,v])=>`${k}=${typeof v==="object"?JSON.stringify(v):v}`).join(" ");console.log(`${ts3} ${level} ${event}${extras?` ${extras}`:""}`)}catch{console.log(raw)}}function formatUptime(ms){let seconds=Math.floor(ms/1000),minutes=Math.floor(seconds/60),hours=Math.floor(minutes/60),days=Math.floor(hours/24);if(days>0)return`${days}d ${hours%24}h ${minutes%60}m`;if(hours>0)return`${hours}h ${minutes%60}m`;if(minutes>0)return`${minutes}m ${seconds%60}s`;return`${seconds}s`}function registerDaemonCommands(program2){let daemon=program2.command("daemon").description("Manage scheduler daemon lifecycle (redirects to genie serve --headless)");daemon.command("install").description("Generate systemd service unit and enable it").action(async()=>{await daemonInstallCommand()}),daemon.command("start").description("Start the scheduler daemon (alias for genie serve --headless)").option("--foreground","Run in foreground (for systemd ExecStart)").action(async(options)=>{await daemonStartCommand(options)}),daemon.command("stop").description("Stop genie serve gracefully").action(async()=>{await daemonStopCommand()}),daemon.command("status").description("Show daemon state, PID, uptime, and trigger stats").action(async()=>{await daemonStatusCommand()}),daemon.command("logs").description("Tail structured JSON scheduler log").option("--follow, -f","Follow log output").option("--lines <n>","Number of lines to show (default: 20)",Number.parseInt).action(async(options)=>{await daemonLogsCommand(options)})}init_cron();import{existsSync as existsSync59,readFileSync as readFileSync41}from"fs";import{dirname as dirname25,join as join71}from"path";import{createInterface as createInterface3}from"readline";init_db();init_wish_state();import{spawnSync as spawnSync8}from"child_process";import{existsSync as existsSync58,mkdirSync as mkdirSync28,readFileSync as readFileSync40,renameSync as renameSync10,statSync as statSync14,writeFileSync as writeFileSync27}from"fs";import{homedir as homedir47}from"os";import{basename as basename10,join as join70,relative as relative4,resolve as resolve14}from"path";import{gunzipSync,gzipSync}from"zlib";var SNAPSHOT_FILE="snapshot.sql.gz";function getSnapshotPath(cwd){let repoRoot=resolveRepoPath(cwd),genieHome6=process.env.GENIE_HOME??join70(homedir47(),".genie");return join70(genieHome6,"backups",basename10(repoRoot),SNAPSHOT_FILE)}function assertOutsideRepo(snapshotPath,cwd){let repoRoot=resolveRepoPath(cwd),rel=relative4(repoRoot,resolve14(snapshotPath));if(!rel.startsWith("..")&&rel!==""&&!rel.startsWith("/"))throw Error(`Refusing to write snapshot inside repo tree: ${snapshotPath}. Snapshots must live outside the repo (default: ~/.genie/backups/<repo>/).`)}function pgEnv(database){let forceTcp=process.env.GENIE_PG_FORCE_TCP==="1",testPort=process.env.GENIE_TEST_PG_PORT,useSocket=!forceTcp&&!testPort,resolvedDatabase=database??resolveDatabaseName();if(useSocket)return{...process.env,PGHOST:resolvePgserveSocketDir(),PGUSER:DB_NAME,PGPASSWORD:resolvePgserveAuthPassword(),PGDATABASE:resolvedDatabase};let port=testPort&&testPort.length>0?testPort:String(getActivePort());return{...process.env,PGHOST:"127.0.0.1",PGPORT:port,PGUSER:DB_NAME,PGPASSWORD:resolveTcpPgPassword(),PGDATABASE:resolvedDatabase}}function backup(cwd){let snapshotPath=getSnapshotPath(cwd);assertOutsideRepo(snapshotPath,cwd);let snapshotDir=snapshotPath.slice(0,snapshotPath.lastIndexOf("/")),tmpPath=`${snapshotPath}.tmp`;mkdirSync28(snapshotDir,{recursive:!0});let result2=spawnSync8("pg_dump",["--no-owner","--no-acl","--clean","--if-exists"],{env:pgEnv(),stdio:["pipe","pipe","pipe"],timeout:120000,maxBuffer:1073741824});if(result2.status!==0){let stderr=result2.stderr?.toString().trim()||"unknown error";throw Error(`pg_dump failed (exit ${result2.status}): ${stderr}`)}let compressed=gzipSync(result2.stdout);writeFileSync27(tmpPath,compressed),renameSync10(tmpPath,snapshotPath);let compressedBytes=statSync14(snapshotPath).size,uncompressedBytes=0;try{let sizeResult=spawnSync8("psql",["-t","-A","-c","SELECT pg_database_size(current_database())"],{env:pgEnv(),encoding:"utf-8",timeout:1e4});if(sizeResult.status===0)uncompressedBytes=Number.parseInt(sizeResult.stdout.trim(),10)||0}catch{}return{path:snapshotPath,compressedBytes,uncompressedBytes}}function restore(snapshotFile,cwd){let filePath=snapshotFile??getSnapshotPath(cwd);if(!existsSync58(filePath))throw Error(`Snapshot not found: ${filePath}`);let env=pgEnv();spawnSync8("psql",["-c","SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = current_database() AND pid <> pg_backend_pid()"],{env,stdio:["pipe","pipe","pipe"],timeout:1e4});let compressed=readFileSync40(filePath),sql=gunzipSync(compressed),restoreResult=spawnSync8("psql",["-v","ON_ERROR_STOP=1"],{env,input:sql,stdio:["pipe","pipe","pipe"],timeout:300000,maxBuffer:1073741824});if(restoreResult.status!==0)throw Error(`psql restore failed (exit ${restoreResult.status}): ${restoreResult.stderr?.toString().trim()}`)}init_db_migrations();init_db();init_term_format();init_src();init_db();var PG_USER2="postgres",PG_PASS2="postgres",PG_HOST2="127.0.0.1",SYSTEM_DBS=new Set(["postgres","template0","template1"]),V2_TENANT_DB_PATTERN=/^app_[a-z0-9_]{1,50}_[0-9a-f]{12}$/;async function dbLsCommand(options){if(!await isAvailable())console.error("Database is not running."),process.exit(1);let v2=await getConnection(),port=await resolveAdminPort(v2),admin=openAdminClient(port);try{let rows=await loadAllDbs(admin),filtered=applyFilters(rows,options);if(options.counts)await enrichWithCounts(filtered,port);if(options.json)console.log(JSON.stringify(filtered,null,2));else printTable(filtered,{showCounts:!!options.counts})}finally{await admin.end({timeout:5})}await shutdown()}async function resolveAdminPort(v2){let portRows=await v2.unsafe("SHOW port"),port=Number(portRows[0]?.port);if(!Number.isFinite(port)||port<=0)console.error("Could not resolve pgserve TCP port."),await shutdown(),process.exit(1);return port}function openAdminClient(port){return src_default({host:PG_HOST2,port,username:PG_USER2,password:PG_PASS2,database:"postgres",max:1,onnotice:()=>{},idle_timeout:5})}function applyFilters(rows,options){let filtered=rows;if(!options.all)filtered=filtered.filter((r)=>!r.isSystem);if(options.orphans)filtered=filtered.filter((r)=>!r.isV2Pattern&&!r.isSystem&&!r.fingerprint);return filtered}async function enrichWithCounts(rows,port){for(let row2 of rows){if(row2.isSystem)continue;await probeRowCounts(row2,port)}}async function probeRowCounts(row2,port){try{let c=src_default({host:PG_HOST2,port,username:PG_USER2,password:PG_PASS2,database:row2.name,max:1,onnotice:()=>{},idle_timeout:1,connect_timeout:3}),probe=await c`
4358
+ `).filter(Boolean);for(let line of newLines)printLogLine(line);lastSize=content.length}}catch{}});process.on("SIGINT",()=>{watcher2.close(),process.exit(0)}),await new Promise(()=>{})}function printLogLine(raw){try{let entry2=JSON.parse(raw),ts3=entry2.timestamp?new Date(entry2.timestamp).toLocaleTimeString("en-US",{hour12:!1}):"??:??:??",level=(entry2.level??"info").toUpperCase().padEnd(5),event=entry2.event??"unknown",extras=Object.entries(entry2).filter(([k])=>!["timestamp","level","event"].includes(k)).map(([k,v])=>`${k}=${typeof v==="object"?JSON.stringify(v):v}`).join(" ");console.log(`${ts3} ${level} ${event}${extras?` ${extras}`:""}`)}catch{console.log(raw)}}function formatUptime(ms){let seconds=Math.floor(ms/1000),minutes=Math.floor(seconds/60),hours=Math.floor(minutes/60),days=Math.floor(hours/24);if(days>0)return`${days}d ${hours%24}h ${minutes%60}m`;if(hours>0)return`${hours}h ${minutes%60}m`;if(minutes>0)return`${minutes}m ${seconds%60}s`;return`${seconds}s`}function registerDaemonCommands(program2){let daemon=program2.command("daemon").description("Manage scheduler daemon lifecycle (redirects to genie serve --headless)");daemon.command("install").description("Generate systemd service unit and enable it").action(async()=>{await daemonInstallCommand()}),daemon.command("start").description("Start the scheduler daemon (alias for genie serve --headless)").option("--foreground","Run in foreground (for systemd ExecStart)").action(async(options)=>{await daemonStartCommand(options)}),daemon.command("stop").description("Stop genie serve gracefully").action(async()=>{await daemonStopCommand()}),daemon.command("status").description("Show daemon state, PID, uptime, and trigger stats").action(async()=>{await daemonStatusCommand()}),daemon.command("logs").description("Tail structured JSON scheduler log").option("--follow, -f","Follow log output").option("--lines <n>","Number of lines to show (default: 20)",Number.parseInt).action(async(options)=>{await daemonLogsCommand(options)})}init_cron();import{existsSync as existsSync59,readFileSync as readFileSync41}from"fs";import{dirname as dirname26,join as join71}from"path";import{createInterface as createInterface3}from"readline";init_db();init_wish_state();import{spawnSync as spawnSync8}from"child_process";import{existsSync as existsSync58,mkdirSync as mkdirSync28,readFileSync as readFileSync40,renameSync as renameSync11,statSync as statSync14,writeFileSync as writeFileSync27}from"fs";import{homedir as homedir47}from"os";import{basename as basename10,join as join70,relative as relative4,resolve as resolve14}from"path";import{gunzipSync,gzipSync}from"zlib";var SNAPSHOT_FILE="snapshot.sql.gz";function getSnapshotPath(cwd){let repoRoot=resolveRepoPath(cwd),genieHome6=process.env.GENIE_HOME??join70(homedir47(),".genie");return join70(genieHome6,"backups",basename10(repoRoot),SNAPSHOT_FILE)}function assertOutsideRepo(snapshotPath,cwd){let repoRoot=resolveRepoPath(cwd),rel=relative4(repoRoot,resolve14(snapshotPath));if(!rel.startsWith("..")&&rel!==""&&!rel.startsWith("/"))throw Error(`Refusing to write snapshot inside repo tree: ${snapshotPath}. Snapshots must live outside the repo (default: ~/.genie/backups/<repo>/).`)}function pgEnv(database){let forceTcp=process.env.GENIE_PG_FORCE_TCP==="1",testPort=process.env.GENIE_TEST_PG_PORT,useSocket=!forceTcp&&!testPort,resolvedDatabase=database??resolveDatabaseName();if(useSocket)return{...process.env,PGHOST:resolvePgserveSocketDir(),PGUSER:DB_NAME,PGPASSWORD:resolvePgserveAuthPassword(),PGDATABASE:resolvedDatabase};let port=testPort&&testPort.length>0?testPort:String(getActivePort());return{...process.env,PGHOST:"127.0.0.1",PGPORT:port,PGUSER:DB_NAME,PGPASSWORD:resolveTcpPgPassword(),PGDATABASE:resolvedDatabase}}function backup(cwd){let snapshotPath=getSnapshotPath(cwd);assertOutsideRepo(snapshotPath,cwd);let snapshotDir=snapshotPath.slice(0,snapshotPath.lastIndexOf("/")),tmpPath=`${snapshotPath}.tmp`;mkdirSync28(snapshotDir,{recursive:!0});let result2=spawnSync8("pg_dump",["--no-owner","--no-acl","--clean","--if-exists"],{env:pgEnv(),stdio:["pipe","pipe","pipe"],timeout:120000,maxBuffer:1073741824});if(result2.status!==0){let stderr=result2.stderr?.toString().trim()||"unknown error";throw Error(`pg_dump failed (exit ${result2.status}): ${stderr}`)}let compressed=gzipSync(result2.stdout);writeFileSync27(tmpPath,compressed),renameSync11(tmpPath,snapshotPath);let compressedBytes=statSync14(snapshotPath).size,uncompressedBytes=0;try{let sizeResult=spawnSync8("psql",["-t","-A","-c","SELECT pg_database_size(current_database())"],{env:pgEnv(),encoding:"utf-8",timeout:1e4});if(sizeResult.status===0)uncompressedBytes=Number.parseInt(sizeResult.stdout.trim(),10)||0}catch{}return{path:snapshotPath,compressedBytes,uncompressedBytes}}function restore(snapshotFile,cwd){let filePath=snapshotFile??getSnapshotPath(cwd);if(!existsSync58(filePath))throw Error(`Snapshot not found: ${filePath}`);let env=pgEnv();spawnSync8("psql",["-c","SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = current_database() AND pid <> pg_backend_pid()"],{env,stdio:["pipe","pipe","pipe"],timeout:1e4});let compressed=readFileSync40(filePath),sql=gunzipSync(compressed),restoreResult=spawnSync8("psql",["-v","ON_ERROR_STOP=1"],{env,input:sql,stdio:["pipe","pipe","pipe"],timeout:300000,maxBuffer:1073741824});if(restoreResult.status!==0)throw Error(`psql restore failed (exit ${restoreResult.status}): ${restoreResult.stderr?.toString().trim()}`)}init_db_migrations();init_db();init_term_format();init_src();init_db();var PG_USER2="postgres",PG_PASS2="postgres",PG_HOST2="127.0.0.1",SYSTEM_DBS=new Set(["postgres","template0","template1"]),V2_TENANT_DB_PATTERN=/^app_[a-z0-9_]{1,50}_[0-9a-f]{12}$/;async function dbLsCommand(options){if(!await isAvailable())console.error("Database is not running."),process.exit(1);let v2=await getConnection(),port=await resolveAdminPort(v2),admin=openAdminClient(port);try{let rows=await loadAllDbs(admin),filtered=applyFilters(rows,options);if(options.counts)await enrichWithCounts(filtered,port);if(options.json)console.log(JSON.stringify(filtered,null,2));else printTable(filtered,{showCounts:!!options.counts})}finally{await admin.end({timeout:5})}await shutdown()}async function resolveAdminPort(v2){let portRows=await v2.unsafe("SHOW port"),port=Number(portRows[0]?.port);if(!Number.isFinite(port)||port<=0)console.error("Could not resolve pgserve TCP port."),await shutdown(),process.exit(1);return port}function openAdminClient(port){return src_default({host:PG_HOST2,port,username:PG_USER2,password:PG_PASS2,database:"postgres",max:1,onnotice:()=>{},idle_timeout:5})}function applyFilters(rows,options){let filtered=rows;if(!options.all)filtered=filtered.filter((r)=>!r.isSystem);if(options.orphans)filtered=filtered.filter((r)=>!r.isV2Pattern&&!r.isSystem&&!r.fingerprint);return filtered}async function enrichWithCounts(rows,port){for(let row2 of rows){if(row2.isSystem)continue;await probeRowCounts(row2,port)}}async function probeRowCounts(row2,port){try{let c=src_default({host:PG_HOST2,port,username:PG_USER2,password:PG_PASS2,database:row2.name,max:1,onnotice:()=>{},idle_timeout:1,connect_timeout:3}),probe=await c`
4356
4359
  SELECT relname, n_live_tup FROM pg_stat_user_tables
4357
4360
  WHERE schemaname='public' AND relname IN ('tasks','wishes','teams','sessions')
4358
4361
  `,counts={};for(let p of probe){let n=Number(p.n_live_tup);if(p.relname==="tasks")counts.tasks=n;else if(p.relname==="wishes")counts.wishes=n;else if(p.relname==="teams")counts.teams=n;else if(p.relname==="sessions")counts.sessions=n}row2.counts=counts,await c.end({timeout:1})}catch{}}async function loadAllDbs(admin){return(await admin`
@@ -4375,7 +4378,7 @@ Genie Scheduler Daemon`),console.log("\u2500".repeat(50)),console.log(` Status:
4375
4378
  WHERE n.nspname='public' AND c.relname=${table} AND a.attnum>0 AND NOT a.attisdropped
4376
4379
  ORDER BY a.attnum
4377
4380
  `}async function migrateOne(v1,v2,table,windowOpt){try{let v1Cols=await getInsertableColumns(v1,table),v2Cols=await getInsertableColumns(v2,table);if(v1Cols.length===0)return{copied:0,skipped:0};if(v2Cols.length===0)return{copied:0,skipped:0,failed:"target lacks table"};let v2Map=new Map(v2Cols.map((c)=>[c.name,c])),cols=v1Cols.map((c)=>c.name).filter((name)=>{let v2c=v2Map.get(name);if(!v2c)return!1;if(v2c.identity==="a")return!1;if(v2c.generated==="s")return!1;return!0});if(cols.length===0)return{copied:0,skipped:0,failed:"no insertable shared columns"};let colList=cols.map((c)=>`"${c}"`).join(","),where=windowOpt?`WHERE "${windowOpt.dateColumn}" > now() - interval '${windowOpt.days} days'`:"",rows=await v1.unsafe(`SELECT ${colList} FROM "${table}" ${where}`);if(rows.length===0)return{copied:0,skipped:0};let copied=0,batchSize=200;for(let i2=0;i2<rows.length;i2+=batchSize){let batch=rows.slice(i2,i2+batchSize),placeholders=batch.map((_,ri)=>`(${cols.map((_2,ci)=>`$${ri*cols.length+ci+1}`).join(",")})`).join(","),values2=batch.flatMap((row2)=>cols.map((c)=>row2[c])),stmt=`INSERT INTO "${table}" (${colList}) VALUES ${placeholders} ON CONFLICT DO NOTHING`,r=await v2.unsafe(stmt,values2);copied+=Number(r.count??0)}return{copied,skipped:rows.length-copied}}catch(err){return{copied:0,skipped:0,failed:err instanceof Error?err.message:String(err)}}}async function archiveV1(port,archive){let admin=src_default({host:V1_HOST,port,username:V1_USER,password:V1_PASS,database:"postgres",max:1,onnotice:()=>{}});try{await admin.unsafe("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname=$1 AND pid<>pg_backend_pid()",[V1_DB_NAME2]),await admin.unsafe(`ALTER DATABASE "${V1_DB_NAME2}" RENAME TO "${archive}"`),await admin.unsafe(`INSERT INTO pgserve_meta (database_name, fingerprint, peer_uid, persist) VALUES ($1, $2, $3, true)
4378
- ON CONFLICT (database_name) DO UPDATE SET persist=true`,[archive,"legacy_v1_archive",0])}finally{await admin.end({timeout:5})}}function report(table,r){if(r.failed)console.log(` \u2717 ${table.padEnd(22)} FAILED: ${r.failed}`);else if(r.copied===0&&r.skipped===0)console.log(` - ${table.padEnd(22)} (no rows)`);else console.log(` \u2713 ${table.padEnd(22)} +${r.copied} copied, ${r.skipped} already present`)}function archiveName(){let d=new Date;return`genie_archive_${d.getFullYear()}${String(d.getMonth()+1).padStart(2,"0")}${String(d.getDate()).padStart(2,"0")}`}function parseDayWindow(value,fallback){if(value===void 0)return fallback;let n=Number.parseInt(value,10);return Number.isFinite(n)&&n>=0?n:fallback}function formatBytes3(n){if(n<1024)return`${n} B`;let u=["KB","MB","GB","TB"],v=n/1024,i2=0;while(v>=1024&&i2<u.length-1)v/=1024,i2++;return`${v.toFixed(1)} ${u[i2]}`}async function confirm(prompt2){return process.stdout.write(`${prompt2} [Y/n]: `),new Promise((resolve15)=>{process.stdin.setEncoding("utf8");let onData=(chunk)=>{let v=chunk.trim().toLowerCase();process.stdin.removeListener("data",onData),process.stdin.pause(),resolve15(v===""||v==="y"||v==="yes")};process.stdin.resume(),process.stdin.once("data",onData)})}function registerDbMigrateV1Command(db){db.command("migrate-v1").description("Migrate v1-era genie data into your v2 fingerprinted workspace").option("--dry-run","Show what would migrate without writing").option("-y, --yes","Skip confirmation prompt").option("--include-sessions <days>","Days of session history to migrate (default 30)").option("--include-audit <days>","Days of audit_events to migrate (default 0 = skipped)").option("--include-content","Also migrate session_content (skipped by default \u2014 large)").option("--no-archive","Don't rename source DB to genie_archive_<date> after migration").action(dbMigrateV1Command)}function findNearestPackageJson(start3){let cwd=start3;while(!0){let candidate=join71(cwd,"package.json");if(existsSync59(candidate))return candidate;let parent=dirname25(cwd);if(parent===cwd)return null;cwd=parent}}function readPersistFlag(start3=process.cwd()){let path3=findNearestPackageJson(start3);if(path3===null)return!1;try{return JSON.parse(readFileSync41(path3,"utf8"))?.pgserve?.persist===!0}catch{return!1}}function printTable2(rows){if(rows.length===0){console.log("(0 rows)");return}let columns=Object.keys(rows[0]),widths=columns.map((col)=>{let values2=rows.map((r)=>String(r[col]??"NULL"));return Math.max(col.length,...values2.map((v)=>v.length))}),header=columns.map((col,i2)=>padRight(col,widths[i2])).join(" | ");console.log(header),console.log(widths.map((w)=>"-".repeat(w)).join("-+-"));for(let row2 of rows){let line=columns.map((col,i2)=>padRight(String(row2[col]??"NULL"),widths[i2])).join(" | ");console.log(line)}console.log(`(${rows.length} row${rows.length===1?"":"s"})`)}function extractFingerprintFromDbName(db){let match=/_([0-9a-f]{12})$/.exec(db);return match?match[1]:null}async function dbStatusCommand(){if(console.log(`
4381
+ ON CONFLICT (database_name) DO UPDATE SET persist=true`,[archive,"legacy_v1_archive",0])}finally{await admin.end({timeout:5})}}function report(table,r){if(r.failed)console.log(` \u2717 ${table.padEnd(22)} FAILED: ${r.failed}`);else if(r.copied===0&&r.skipped===0)console.log(` - ${table.padEnd(22)} (no rows)`);else console.log(` \u2713 ${table.padEnd(22)} +${r.copied} copied, ${r.skipped} already present`)}function archiveName(){let d=new Date;return`genie_archive_${d.getFullYear()}${String(d.getMonth()+1).padStart(2,"0")}${String(d.getDate()).padStart(2,"0")}`}function parseDayWindow(value,fallback){if(value===void 0)return fallback;let n=Number.parseInt(value,10);return Number.isFinite(n)&&n>=0?n:fallback}function formatBytes3(n){if(n<1024)return`${n} B`;let u=["KB","MB","GB","TB"],v=n/1024,i2=0;while(v>=1024&&i2<u.length-1)v/=1024,i2++;return`${v.toFixed(1)} ${u[i2]}`}async function confirm(prompt2){return process.stdout.write(`${prompt2} [Y/n]: `),new Promise((resolve15)=>{process.stdin.setEncoding("utf8");let onData=(chunk)=>{let v=chunk.trim().toLowerCase();process.stdin.removeListener("data",onData),process.stdin.pause(),resolve15(v===""||v==="y"||v==="yes")};process.stdin.resume(),process.stdin.once("data",onData)})}function registerDbMigrateV1Command(db){db.command("migrate-v1").description("Migrate v1-era genie data into your v2 fingerprinted workspace").option("--dry-run","Show what would migrate without writing").option("-y, --yes","Skip confirmation prompt").option("--include-sessions <days>","Days of session history to migrate (default 30)").option("--include-audit <days>","Days of audit_events to migrate (default 0 = skipped)").option("--include-content","Also migrate session_content (skipped by default \u2014 large)").option("--no-archive","Don't rename source DB to genie_archive_<date> after migration").action(dbMigrateV1Command)}function findNearestPackageJson(start3){let cwd=start3;while(!0){let candidate=join71(cwd,"package.json");if(existsSync59(candidate))return candidate;let parent=dirname26(cwd);if(parent===cwd)return null;cwd=parent}}function readPersistFlag(start3=process.cwd()){let path3=findNearestPackageJson(start3);if(path3===null)return!1;try{return JSON.parse(readFileSync41(path3,"utf8"))?.pgserve?.persist===!0}catch{return!1}}function printTable2(rows){if(rows.length===0){console.log("(0 rows)");return}let columns=Object.keys(rows[0]),widths=columns.map((col)=>{let values2=rows.map((r)=>String(r[col]??"NULL"));return Math.max(col.length,...values2.map((v)=>v.length))}),header=columns.map((col,i2)=>padRight(col,widths[i2])).join(" | ");console.log(header),console.log(widths.map((w)=>"-".repeat(w)).join("-+-"));for(let row2 of rows){let line=columns.map((col,i2)=>padRight(String(row2[col]??"NULL"),widths[i2])).join(" | ");console.log(line)}console.log(`(${rows.length} row${rows.length===1?"":"s"})`)}function extractFingerprintFromDbName(db){let match=/_([0-9a-f]{12})$/.exec(db);return match?match[1]:null}async function dbStatusCommand(){if(console.log(`
4379
4382
  Genie Database Status`),console.log("\u2500".repeat(50)),!await isAvailable()){let socketPath=resolvePgserveLibpqSocketPath();console.log(" Status: stopped"),console.log(` Socket: ${socketPath} (not bound)`),console.log(`
4380
4383
  pgserve daemon is not running. Start it with one of:`),console.log(" npx pgserve daemon # foreground"),console.log(" pm2 start node_modules/pgserve/bin/pgserve-wrapper.cjs -- daemon # background"),console.log(" Genie will also auto-start the daemon on first connect."),console.log("");return}console.log(" Status: running");try{let sql=await getConnection();if(isSocketMode()){let socketDir=resolvePgserveSocketDir(),rows=await sql`SELECT current_database() AS db`,db=String(rows[0]?.db??""),fingerprint=extractFingerprintFromDbName(db),persist=readPersistFlag();console.log(" Mode: socket (pgserve v2)"),console.log(` Socket: ${socketDir}/.s.PGSQL.5432`),console.log(` Database: ${db}`),console.log(` Fingerprint: ${fingerprint??"(non-standard name)"}`),console.log(` Persist: ${persist}${persist?"":" (eligible for 24h TTL reap)"}`)}else{let port=getActivePort();console.log(" Mode: tcp (legacy)"),console.log(" Host: 127.0.0.1"),console.log(` Port: ${port}`),console.log(` Data dir: ${getDataDir()}`)}let sizeResult=await sql`SELECT pg_size_pretty(pg_database_size(current_database())) AS size`;console.log(` DB size: ${sizeResult[0].size}`);let migrations=await getMigrationStatus(sql);console.log(`
4381
4384
  Migrations: ${migrations.applied.length} applied, ${migrations.pending.length} pending`);let tables=await sql`
@@ -4393,8 +4396,8 @@ Done. ${results.length} migration${results.length===1?"":"s"} applied.`),await s
4393
4396
  `,count=Number(rows[0].cnt);console.log(`Would delete ${count} event${count===1?"":"s"} older than ${options.olderThan}.`)}else{let result2=await sql`
4394
4397
  DELETE FROM genie_runtime_events
4395
4398
  WHERE created_at < now() - make_interval(secs => ${intervalSec})
4396
- `,count=Number(result2.count);console.log(`Deleted ${count} event${count===1?"":"s"} older than ${options.olderThan}.`)}await shutdown()}catch(err){let message=err instanceof Error?err.message:String(err);console.error(`Prune failed: ${message}`),process.exit(1)}}function registerDbCommands(program2){let db=program2.command("db").description("Database management (pgserve)");db.command("status").description("Show pgserve health, port, data dir, and table counts").action(dbStatusCommand),db.command("migrate").description("Run pending database migrations").action(dbMigrateCommand),db.command("query <sql>").description("Execute arbitrary SQL and print results").action(dbQueryCommand),db.command("url").description("Print postgres connection URL for direct access").option("--quiet","Print URL only, no trailing newline (for scripts)").action(async(options)=>{await isAvailable();let url;if(isSocketMode())url=`postgresql:///postgres?host=${resolvePgserveSocketDir()}`;else url=`postgres://postgres:postgres@127.0.0.1:${getActivePort()}/genie`;if(options.quiet)process.stdout.write(url);else console.log(url);await shutdown()}),db.command("prune-events").description("Prune old runtime events beyond retention period").option("--older-than <duration>","Delete events older than (e.g., 30d, 7d)","14d").option("--dry-run","Show count without deleting").action(dbPruneEventsCommand),db.command("backup").description("Dump database to .genie/snapshot.sql.gz").action(dbBackupCommand),db.command("restore [file]").description("Restore database from snapshot (default: .genie/snapshot.sql.gz)").option("-y, --yes","Skip confirmation prompt").action(dbRestoreCommand),registerDbMigrateV1Command(db),registerDbLsCommand(db)}init_dispatch();function registerDispatchGroupCommands(program2){let dispatch3=program2.command("dispatch").description("Framework skill dispatch primitives (brainstorm/wish/review)");dispatch3.command("brainstorm <agent> <slug>").description("Spawn agent with brainstorm DRAFT.md context").action(async(agent,slug)=>{await brainstormCommand(agent,slug)}),dispatch3.command("wish <agent> <slug>").description("Spawn agent with wish DESIGN.md context").action(async(agent,slug)=>{await wishCommand(agent,slug)}),dispatch3.command("review <agent> <ref>").description("Spawn agent with review scope for a wish group (format: <slug>#<group>)").action(async(agent,ref)=>{await reviewCommand(agent,ref)})}init_dispatch();init_export_format();import{existsSync as existsSync66,mkdirSync as mkdirSync30,writeFileSync as writeFileSync28}from"fs";import{dirname as dirname27}from"path";async function getSql(){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return getConnection2()}async function getVersion(){let{VERSION:VERSION2}=await Promise.resolve().then(() => (init_version(),exports_version));return VERSION2}async function getActorName(){let{getActor:getActor2}=await Promise.resolve().then(() => (init_audit(),exports_audit));return getActor2()}async function detectTables(sql,tables){let{filterAvailableTables:filterAvailableTables2}=await Promise.resolve().then(() => exports_table_detect);return filterAvailableTables2(sql,tables)}function outputDocument(doc,options){let json2=options.pretty?JSON.stringify(doc,null,2):JSON.stringify(doc);if(options.output){let dir=dirname27(options.output);if(!existsSync66(dir))mkdirSync30(dir,{recursive:!0});writeFileSync28(options.output,`${json2}
4397
- `);let tables=Object.keys(doc.data),rows=Object.values(doc.data).reduce((sum,arr)=>sum+arr.length,0);if(console.log(`Exported ${tables.length} tables (${rows} rows) to ${options.output}`),doc.skippedTables.length>0)console.log(`Skipped tables (not found): ${doc.skippedTables.join(", ")}`)}else console.log(json2)}function autoOutputName(){let d=new Date;return`genie-backup-${`${d.getFullYear()}${String(d.getMonth()+1).padStart(2,"0")}${String(d.getDate()).padStart(2,"0")}`}.json`}async function exportGroup(sql,group,filter){let tables=GROUP_TABLES[group],{available,skipped}=await detectTables(sql,tables),data={};for(let table of available)if(filter)data[table]=[...await sql.unsafe(`SELECT * FROM ${table} WHERE ${filter.column} = $1`,[filter.value])];else data[table]=[...await sql.unsafe(`SELECT * FROM ${table}`)];return{data,skipped}}async function exportBoards(sql,name){let tables=GROUP_TABLES.boards,{available,skipped}=await detectTables(sql,tables),data={};for(let table of available)if(name&&table==="boards")data[table]=[...await sql`SELECT * FROM boards WHERE name = ${name}`];else if(table==="task_types")data[table]=[...await sql`SELECT * FROM task_types WHERE is_builtin = false`];else data[table]=[...await sql.unsafe(`SELECT * FROM ${table}`)];return{data,skipped}}var TASK_JOIN_ALIASES={task_tags:"tt",task_actors:"ta",task_dependencies:"td",task_stage_log:"tsl"};async function resolveProjectId2(sql,projectName){let projects=await sql`SELECT id FROM projects WHERE name = ${projectName}`;if(projects.length===0)throw Error(`Project not found: ${projectName}`);return projects[0].id}function stripEphemeralFields(rows){return rows.map((r)=>{let{checkout_run_id,execution_locked_at,session_id,pane_id,...rest}=r;return rest})}async function exportTaskTable(sql,table,projectId){let alias=TASK_JOIN_ALIASES[table];if(table==="tasks"){let rows=projectId?[...await sql.unsafe("SELECT * FROM tasks WHERE project_id = $1",[projectId])]:[...await sql`SELECT * FROM tasks`];return stripEphemeralFields(rows)}if(alias&&projectId)return[...await sql.unsafe(`SELECT ${alias}.* FROM ${table} ${alias} JOIN tasks t ON ${alias}.task_id = t.id WHERE t.project_id = $1`,[projectId])];return[...await sql.unsafe(`SELECT * FROM ${table}`)]}async function exportTasks(sql,projectName){let tables=GROUP_TABLES.tasks,{available,skipped}=await detectTables(sql,tables),data={},projectId=projectName?await resolveProjectId2(sql,projectName):null;for(let table of available)data[table]=await exportTaskTable(sql,table,projectId);return{data,skipped}}async function exportSchedules(sql,name){let{available,skipped}=await detectTables(sql,["schedules"]),data={};if(available.includes("schedules"))if(name)data.schedules=[...await sql`SELECT * FROM schedules WHERE name = ${name}`];else data.schedules=[...await sql`SELECT * FROM schedules`];return{data,skipped}}async function exportTags(sql){let{available,skipped}=await detectTables(sql,["tags"]),data={};if(available.includes("tags"))data.tags=[...await sql`SELECT * FROM tags WHERE name NOT LIKE 'test-%'`];return{data,skipped}}async function exportAll(sql){let allSkipped=[],allData={};for(let group of ALL_GROUPS){let result2;switch(group){case"boards":result2=await exportBoards(sql);break;case"tasks":result2=await exportTasks(sql);break;case"tags":result2=await exportTags(sql);break;case"schedules":result2=await exportSchedules(sql);break;default:result2=await exportGroup(sql,group);break}Object.assign(allData,result2.data),allSkipped.push(...result2.skipped)}return{data:allData,skipped:allSkipped}}async function runExport(groups,type2,exportFn,options){let sql=await getSql(),[version,actor]=await Promise.all([getVersion(),getActorName()]),doc=createExportDocument(type2,groups,version,actor),{data,skipped}=await exportFn(sql);doc.data=data,doc.skippedTables=skipped,outputDocument(doc,options)}function registerExportCommands(program2){let exp=program2.command("export").description("Export genie data as JSON").option("--output <file>","Write to file instead of stdout").option("-o <file>","Alias for --output").option("--pretty","Pretty-print JSON").action(async(options)=>{try{if(!options.output)options.output=autoOutputName();await runExport([...ALL_GROUPS],"full",(sql)=>exportAll(sql),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts=(cmd)=>cmd.option("--output <file>","Write to file instead of stdout").option("--pretty","Pretty-print JSON");sharedOpts(exp.command("all").description("Full backup (all present tables)")).action(async(options)=>{try{if(!options.output)options.output=autoOutputName();await runExport([...ALL_GROUPS],"full",(sql)=>exportAll(sql),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("boards [name]").description("Export boards, templates, and task types")).action(async(name,options)=>{try{await runExport(["boards"],"partial",(sql)=>exportBoards(sql,name),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("tasks").description("Export tasks with deps, actors, and stage log").option("--project <name>","Filter by project name")).action(async(options)=>{try{await runExport(["tasks"],"partial",(sql)=>exportTasks(sql,options.project),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("tags").description("Export tags")).action(async(options)=>{try{await runExport(["tags"],"partial",(sql)=>exportTags(sql),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("projects").description("Export projects")).action(async(options)=>{try{await runExport(["projects"],"partial",(sql)=>exportGroup(sql,"projects"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("schedules [name]").description("Export schedules with run_spec")).action(async(name,options)=>{try{await runExport(["schedules"],"partial",(sql)=>exportSchedules(sql,name),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("agents").description("Export agents, templates, and checkpoints")).action(async(options)=>{try{await runExport(["agents"],"partial",(sql)=>exportGroup(sql,"agents"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("comms").description("Export conversations, messages, mailbox")).action(async(options)=>{try{await runExport(["comms"],"partial",(sql)=>exportGroup(sql,"comms"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("config").description("Export OS config (graceful skip if missing)")).action(async(options)=>{try{await runExport(["config"],"partial",(sql)=>exportGroup(sql,"config"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_history();init_export_format();import{readFileSync as readFileSync43}from"fs";var IMPORT_LEVELS=[["schedules","sessions","projects","agent_templates","agent_checkpoints","tags","task_types","notification_preferences","os_config","golden_images","warm_pool","instances"],["triggers","boards","board_templates","agents","conversations"],["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"]}var VALID_TABLES=new Set(Object.values(GROUP_TABLES).flat());function assertValidTable(name){if(!VALID_TABLES.has(name))throw Error(`Invalid table name: "${name}" is not in the schema whitelist`)}var VALID_COLUMN_RE=/^[a-zA-Z_][a-zA-Z0-9_]*$/;function assertValidColumnName(name){if(!VALID_COLUMN_RE.test(name))throw Error(`Invalid column name: "${name.slice(0,60)}" contains disallowed characters. Column names must match /^[a-zA-Z_][a-zA-Z0-9_]*$/.`)}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[];assertValidTable(table);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 row2 of rows){let conditions=pk.map((col,i2)=>`${col} = $${i2+1}`).join(" AND "),values2=pk.map((col)=>row2[col]);if((await sql.unsafe(`SELECT 1 FROM ${table} WHERE ${conditions} LIMIT 1`,values2)).length>0)conflicts.push(row2)}return conflicts}function prepareRow(row2,table,selfRefUpdates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],entries=Object.entries(row2),columns=entries.map(([k])=>k),values2=entries.map(([,v])=>v);for(let col of columns)assertValidColumnName(col);if(selfRefCol&&row2[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?row2[pk[0]]:pk.map((k)=>row2[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,row2,prepared,mode){assertValidTable(table);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)=>row2[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){assertValidTable(table);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 row2 of rows){let prepared=prepareRow(row2,table,selfRefUpdates);await insertOneRow(tx,table,row2,prepared,mode)}if(selfRefUpdates.length>0)await updateSelfRefs(tx,table,selfRefUpdates);return rows.length}function parseExportFile(filePath){let raw=readFileSync43(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:recordAuditEvent3}=await Promise.resolve().then(() => (init_audit(),exports_audit));await recordAuditEvent3("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_esm14();import{existsSync as existsSync70,mkdirSync as mkdirSync33,symlinkSync,writeFileSync as writeFileSync31}from"fs";import{basename as basename12,join as join82,relative as relative7,resolve as resolve16,sep as sep2}from"path";import{cpSync,existsSync as existsSync68,mkdirSync as mkdirSync31,renameSync as renameSync12,rmSync as rmSync4}from"fs";import{join as join79,relative as relative6}from"path";var import_ignore=__toESM(require_ignore(),1);import{existsSync as existsSync67,readFileSync as readFileSync44,readdirSync as readdirSync15,statSync as statSync16}from"fs";import{join as join78,relative as relative5}from"path";var GENIEIGNORE_DEFAULTS=`node_modules
4399
+ `,count=Number(result2.count);console.log(`Deleted ${count} event${count===1?"":"s"} older than ${options.olderThan}.`)}await shutdown()}catch(err){let message=err instanceof Error?err.message:String(err);console.error(`Prune failed: ${message}`),process.exit(1)}}function registerDbCommands(program2){let db=program2.command("db").description("Database management (pgserve)");db.command("status").description("Show pgserve health, port, data dir, and table counts").action(dbStatusCommand),db.command("migrate").description("Run pending database migrations").action(dbMigrateCommand),db.command("query <sql>").description("Execute arbitrary SQL and print results").action(dbQueryCommand),db.command("url").description("Print postgres connection URL for direct access").option("--quiet","Print URL only, no trailing newline (for scripts)").action(async(options)=>{await isAvailable();let url;if(isSocketMode())url=`postgresql:///postgres?host=${resolvePgserveSocketDir()}`;else url=`postgres://postgres:postgres@127.0.0.1:${getActivePort()}/genie`;if(options.quiet)process.stdout.write(url);else console.log(url);await shutdown()}),db.command("prune-events").description("Prune old runtime events beyond retention period").option("--older-than <duration>","Delete events older than (e.g., 30d, 7d)","14d").option("--dry-run","Show count without deleting").action(dbPruneEventsCommand),db.command("backup").description("Dump database to .genie/snapshot.sql.gz").action(dbBackupCommand),db.command("restore [file]").description("Restore database from snapshot (default: .genie/snapshot.sql.gz)").option("-y, --yes","Skip confirmation prompt").action(dbRestoreCommand),registerDbMigrateV1Command(db),registerDbLsCommand(db)}init_dispatch();function registerDispatchGroupCommands(program2){let dispatch3=program2.command("dispatch").description("Framework skill dispatch primitives (brainstorm/wish/review)");dispatch3.command("brainstorm <agent> <slug>").description("Spawn agent with brainstorm DRAFT.md context").action(async(agent,slug)=>{await brainstormCommand(agent,slug)}),dispatch3.command("wish <agent> <slug>").description("Spawn agent with wish DESIGN.md context").action(async(agent,slug)=>{await wishCommand(agent,slug)}),dispatch3.command("review <agent> <ref>").description("Spawn agent with review scope for a wish group (format: <slug>#<group>)").action(async(agent,ref)=>{await reviewCommand(agent,ref)})}init_dispatch();init_export_format();import{existsSync as existsSync66,mkdirSync as mkdirSync30,writeFileSync as writeFileSync28}from"fs";import{dirname as dirname28}from"path";async function getSql(){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return getConnection2()}async function getVersion(){let{VERSION:VERSION2}=await Promise.resolve().then(() => (init_version(),exports_version));return VERSION2}async function getActorName(){let{getActor:getActor2}=await Promise.resolve().then(() => (init_audit(),exports_audit));return getActor2()}async function detectTables(sql,tables){let{filterAvailableTables:filterAvailableTables2}=await Promise.resolve().then(() => exports_table_detect);return filterAvailableTables2(sql,tables)}function outputDocument(doc,options){let json2=options.pretty?JSON.stringify(doc,null,2):JSON.stringify(doc);if(options.output){let dir=dirname28(options.output);if(!existsSync66(dir))mkdirSync30(dir,{recursive:!0});writeFileSync28(options.output,`${json2}
4400
+ `);let tables=Object.keys(doc.data),rows=Object.values(doc.data).reduce((sum,arr)=>sum+arr.length,0);if(console.log(`Exported ${tables.length} tables (${rows} rows) to ${options.output}`),doc.skippedTables.length>0)console.log(`Skipped tables (not found): ${doc.skippedTables.join(", ")}`)}else console.log(json2)}function autoOutputName(){let d=new Date;return`genie-backup-${`${d.getFullYear()}${String(d.getMonth()+1).padStart(2,"0")}${String(d.getDate()).padStart(2,"0")}`}.json`}async function exportGroup(sql,group,filter){let tables=GROUP_TABLES[group],{available,skipped}=await detectTables(sql,tables),data={};for(let table of available)if(filter)data[table]=[...await sql.unsafe(`SELECT * FROM ${table} WHERE ${filter.column} = $1`,[filter.value])];else data[table]=[...await sql.unsafe(`SELECT * FROM ${table}`)];return{data,skipped}}async function exportBoards(sql,name){let tables=GROUP_TABLES.boards,{available,skipped}=await detectTables(sql,tables),data={};for(let table of available)if(name&&table==="boards")data[table]=[...await sql`SELECT * FROM boards WHERE name = ${name}`];else if(table==="task_types")data[table]=[...await sql`SELECT * FROM task_types WHERE is_builtin = false`];else data[table]=[...await sql.unsafe(`SELECT * FROM ${table}`)];return{data,skipped}}var TASK_JOIN_ALIASES={task_tags:"tt",task_actors:"ta",task_dependencies:"td",task_stage_log:"tsl"};async function resolveProjectId2(sql,projectName){let projects=await sql`SELECT id FROM projects WHERE name = ${projectName}`;if(projects.length===0)throw Error(`Project not found: ${projectName}`);return projects[0].id}function stripEphemeralFields(rows){return rows.map((r)=>{let{checkout_run_id,execution_locked_at,session_id,pane_id,...rest}=r;return rest})}async function exportTaskTable(sql,table,projectId){let alias=TASK_JOIN_ALIASES[table];if(table==="tasks"){let rows=projectId?[...await sql.unsafe("SELECT * FROM tasks WHERE project_id = $1",[projectId])]:[...await sql`SELECT * FROM tasks`];return stripEphemeralFields(rows)}if(alias&&projectId)return[...await sql.unsafe(`SELECT ${alias}.* FROM ${table} ${alias} JOIN tasks t ON ${alias}.task_id = t.id WHERE t.project_id = $1`,[projectId])];return[...await sql.unsafe(`SELECT * FROM ${table}`)]}async function exportTasks(sql,projectName){let tables=GROUP_TABLES.tasks,{available,skipped}=await detectTables(sql,tables),data={},projectId=projectName?await resolveProjectId2(sql,projectName):null;for(let table of available)data[table]=await exportTaskTable(sql,table,projectId);return{data,skipped}}async function exportSchedules(sql,name){let{available,skipped}=await detectTables(sql,["schedules"]),data={};if(available.includes("schedules"))if(name)data.schedules=[...await sql`SELECT * FROM schedules WHERE name = ${name}`];else data.schedules=[...await sql`SELECT * FROM schedules`];return{data,skipped}}async function exportTags(sql){let{available,skipped}=await detectTables(sql,["tags"]),data={};if(available.includes("tags"))data.tags=[...await sql`SELECT * FROM tags WHERE name NOT LIKE 'test-%'`];return{data,skipped}}async function exportAll(sql){let allSkipped=[],allData={};for(let group of ALL_GROUPS){let result2;switch(group){case"boards":result2=await exportBoards(sql);break;case"tasks":result2=await exportTasks(sql);break;case"tags":result2=await exportTags(sql);break;case"schedules":result2=await exportSchedules(sql);break;default:result2=await exportGroup(sql,group);break}Object.assign(allData,result2.data),allSkipped.push(...result2.skipped)}return{data:allData,skipped:allSkipped}}async function runExport(groups,type2,exportFn,options){let sql=await getSql(),[version,actor]=await Promise.all([getVersion(),getActorName()]),doc=createExportDocument(type2,groups,version,actor),{data,skipped}=await exportFn(sql);doc.data=data,doc.skippedTables=skipped,outputDocument(doc,options)}function registerExportCommands(program2){let exp=program2.command("export").description("Export genie data as JSON").option("--output <file>","Write to file instead of stdout").option("-o <file>","Alias for --output").option("--pretty","Pretty-print JSON").action(async(options)=>{try{if(!options.output)options.output=autoOutputName();await runExport([...ALL_GROUPS],"full",(sql)=>exportAll(sql),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts=(cmd)=>cmd.option("--output <file>","Write to file instead of stdout").option("--pretty","Pretty-print JSON");sharedOpts(exp.command("all").description("Full backup (all present tables)")).action(async(options)=>{try{if(!options.output)options.output=autoOutputName();await runExport([...ALL_GROUPS],"full",(sql)=>exportAll(sql),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("boards [name]").description("Export boards, templates, and task types")).action(async(name,options)=>{try{await runExport(["boards"],"partial",(sql)=>exportBoards(sql,name),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("tasks").description("Export tasks with deps, actors, and stage log").option("--project <name>","Filter by project name")).action(async(options)=>{try{await runExport(["tasks"],"partial",(sql)=>exportTasks(sql,options.project),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("tags").description("Export tags")).action(async(options)=>{try{await runExport(["tags"],"partial",(sql)=>exportTags(sql),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("projects").description("Export projects")).action(async(options)=>{try{await runExport(["projects"],"partial",(sql)=>exportGroup(sql,"projects"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("schedules [name]").description("Export schedules with run_spec")).action(async(name,options)=>{try{await runExport(["schedules"],"partial",(sql)=>exportSchedules(sql,name),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("agents").description("Export agents, templates, and checkpoints")).action(async(options)=>{try{await runExport(["agents"],"partial",(sql)=>exportGroup(sql,"agents"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("comms").description("Export conversations, messages, mailbox")).action(async(options)=>{try{await runExport(["comms"],"partial",(sql)=>exportGroup(sql,"comms"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),sharedOpts(exp.command("config").description("Export OS config (graceful skip if missing)")).action(async(options)=>{try{await runExport(["config"],"partial",(sql)=>exportGroup(sql,"config"),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_history();init_export_format();import{readFileSync as readFileSync43}from"fs";var IMPORT_LEVELS=[["schedules","sessions","projects","agent_templates","agent_checkpoints","tags","task_types","notification_preferences","os_config","golden_images","warm_pool","instances"],["triggers","boards","board_templates","agents","conversations"],["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"]}var VALID_TABLES=new Set(Object.values(GROUP_TABLES).flat());function assertValidTable(name){if(!VALID_TABLES.has(name))throw Error(`Invalid table name: "${name}" is not in the schema whitelist`)}var VALID_COLUMN_RE=/^[a-zA-Z_][a-zA-Z0-9_]*$/;function assertValidColumnName(name){if(!VALID_COLUMN_RE.test(name))throw Error(`Invalid column name: "${name.slice(0,60)}" contains disallowed characters. Column names must match /^[a-zA-Z_][a-zA-Z0-9_]*$/.`)}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[];assertValidTable(table);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 row2 of rows){let conditions=pk.map((col,i2)=>`${col} = $${i2+1}`).join(" AND "),values2=pk.map((col)=>row2[col]);if((await sql.unsafe(`SELECT 1 FROM ${table} WHERE ${conditions} LIMIT 1`,values2)).length>0)conflicts.push(row2)}return conflicts}function prepareRow(row2,table,selfRefUpdates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],entries=Object.entries(row2),columns=entries.map(([k])=>k),values2=entries.map(([,v])=>v);for(let col of columns)assertValidColumnName(col);if(selfRefCol&&row2[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?row2[pk[0]]:pk.map((k)=>row2[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,row2,prepared,mode){assertValidTable(table);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)=>row2[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){assertValidTable(table);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 row2 of rows){let prepared=prepareRow(row2,table,selfRefUpdates);await insertOneRow(tx,table,row2,prepared,mode)}if(selfRefUpdates.length>0)await updateSelfRefs(tx,table,selfRefUpdates);return rows.length}function parseExportFile(filePath){let raw=readFileSync43(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:recordAuditEvent3}=await Promise.resolve().then(() => (init_audit(),exports_audit));await recordAuditEvent3("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_esm14();import{existsSync as existsSync70,mkdirSync as mkdirSync33,symlinkSync,writeFileSync as writeFileSync31}from"fs";import{basename as basename12,join as join82,relative as relative7,resolve as resolve16,sep as sep2}from"path";import{cpSync,existsSync as existsSync68,mkdirSync as mkdirSync31,renameSync as renameSync13,rmSync as rmSync4}from"fs";import{join as join79,relative as relative6}from"path";var import_ignore=__toESM(require_ignore(),1);import{existsSync as existsSync67,readFileSync as readFileSync44,readdirSync as readdirSync15,statSync as statSync16}from"fs";import{join as join78,relative as relative5}from"path";var GENIEIGNORE_DEFAULTS=`node_modules
4398
4401
  .git
4399
4402
  .genie/worktrees
4400
4403
  dist
@@ -4407,7 +4410,7 @@ __pycache__
4407
4410
  target
4408
4411
  coverage
4409
4412
  .cache
4410
- `;function loadIgnoreRules(ignoreFilePath){let ig=import_ignore.default();if(existsSync67(ignoreFilePath)){let content=readFileSync44(ignoreFilePath,"utf-8");ig.add(content)}return ig}async function*scanForAgents(root,ignoreFilePath){let ig=loadIgnoreRules(ignoreFilePath??join78(root,".genieignore"));ig.add("agents"),yield*walkDir(root,root,ig)}function*walkDir(dir,root,ig){let names;try{names=readdirSync15(dir)}catch{return}for(let name of names){let fullPath=join78(dir,name);try{if(!statSync16(fullPath).isDirectory())continue}catch{continue}let relPath=`${relative5(root,fullPath)}/`;if(ig.ignores(relPath))continue;let agentsMdPath=join78(fullPath,"AGENTS.md");if(existsSync67(agentsMdPath)){let hasSubAgents=hasSubAgentDirs(fullPath);if(yield{path:fullPath,dirName:name,hasSubAgents,isSubAgent:!1},hasSubAgents)yield*scanSubAgents2(fullPath,name)}yield*walkDir(fullPath,root,ig)}}function hasSubAgentDirs(agentDir){let subAgentsDir=join78(agentDir,".genie","agents");if(!existsSync67(subAgentsDir))return!1;try{return readdirSync15(subAgentsDir).some((name)=>{let subPath=join78(subAgentsDir,name);try{return statSync16(subPath).isDirectory()&&existsSync67(join78(subPath,"AGENTS.md"))}catch{return!1}})}catch{return!1}}function*scanSubAgents2(parentDir,parentName){let subAgentsDir=join78(parentDir,".genie","agents");if(!existsSync67(subAgentsDir))return;let names;try{names=readdirSync15(subAgentsDir)}catch{return}for(let name of names){let subDir=join78(subAgentsDir,name);try{if(!statSync16(subDir).isDirectory())continue}catch{continue}if(!existsSync67(join78(subDir,"AGENTS.md")))continue;yield{path:subDir,dirName:name,hasSubAgents:!1,isSubAgent:!0,parentName}}}async function scanForAgentsAll(root,ignoreFilePath){let results=[];for await(let agent of scanForAgents(root,ignoreFilePath))results.push(agent);return results}init_workspace();async function discoverExternalAgents(workspaceRoot){let allScanned=await scanForAgentsAll(workspaceRoot),canonicalNames=new Set(scanAgents2(workspaceRoot)),agentsDir=join79(workspaceRoot,"agents"),external2=[];for(let scanned of allScanned){if(scanned.path.startsWith(agentsDir))continue;if(canonicalNames.has(scanned.dirName))continue;external2.push({name:scanned.dirName,path:scanned.path,relativePath:relative6(workspaceRoot,scanned.path),isSubAgent:scanned.isSubAgent,parentName:scanned.parentName})}return external2}function importAgents(workspaceRoot,agents){let agentsDir=join79(workspaceRoot,"agents");mkdirSync31(agentsDir,{recursive:!0});let result2={imported:[],skipped:[],errors:[]};for(let agent of agents){let destName=resolveUniqueName(agentsDir,agent.name),destPath=join79(agentsDir,destName);if(existsSync68(destPath)){result2.skipped.push(agent.name);continue}try{moveDirectory(agent.path,destPath),result2.imported.push(destName)}catch(err){result2.errors.push({name:agent.name,error:err instanceof Error?err.message:String(err)})}}return result2}function moveDirectory(src,dest){try{renameSync12(src,dest)}catch{cpSync(src,dest,{recursive:!0}),rmSync4(src,{recursive:!0,force:!0})}}function resolveUniqueName(agentsDir,name){if(!existsSync68(join79(agentsDir,name)))return name;let suffix=2;while(existsSync68(join79(agentsDir,`${name}-${suffix}`)))suffix++;return`${name}-${suffix}`}init_interactivity();init_defaults();import{readFileSync as readFileSync45,writeFileSync as writeFileSync29}from"fs";import{join as join80}from"path";function formatDefaults(workspaceDefaults){let effective=computeEffectiveDefaults(workspaceDefaults),lines=[];for(let key of Object.keys(BUILTIN_DEFAULTS)){let value=effective[key],source=workspaceDefaults?.[key]!==void 0?"workspace":"built-in";lines.push(` ${key}: ${value} (${source})`)}return lines.join(`
4413
+ `;function loadIgnoreRules(ignoreFilePath){let ig=import_ignore.default();if(existsSync67(ignoreFilePath)){let content=readFileSync44(ignoreFilePath,"utf-8");ig.add(content)}return ig}async function*scanForAgents(root,ignoreFilePath){let ig=loadIgnoreRules(ignoreFilePath??join78(root,".genieignore"));ig.add("agents"),yield*walkDir(root,root,ig)}function*walkDir(dir,root,ig){let names;try{names=readdirSync15(dir)}catch{return}for(let name of names){let fullPath=join78(dir,name);try{if(!statSync16(fullPath).isDirectory())continue}catch{continue}let relPath=`${relative5(root,fullPath)}/`;if(ig.ignores(relPath))continue;let agentsMdPath=join78(fullPath,"AGENTS.md");if(existsSync67(agentsMdPath)){let hasSubAgents=hasSubAgentDirs(fullPath);if(yield{path:fullPath,dirName:name,hasSubAgents,isSubAgent:!1},hasSubAgents)yield*scanSubAgents2(fullPath,name)}yield*walkDir(fullPath,root,ig)}}function hasSubAgentDirs(agentDir){let subAgentsDir=join78(agentDir,".genie","agents");if(!existsSync67(subAgentsDir))return!1;try{return readdirSync15(subAgentsDir).some((name)=>{let subPath=join78(subAgentsDir,name);try{return statSync16(subPath).isDirectory()&&existsSync67(join78(subPath,"AGENTS.md"))}catch{return!1}})}catch{return!1}}function*scanSubAgents2(parentDir,parentName){let subAgentsDir=join78(parentDir,".genie","agents");if(!existsSync67(subAgentsDir))return;let names;try{names=readdirSync15(subAgentsDir)}catch{return}for(let name of names){let subDir=join78(subAgentsDir,name);try{if(!statSync16(subDir).isDirectory())continue}catch{continue}if(!existsSync67(join78(subDir,"AGENTS.md")))continue;yield{path:subDir,dirName:name,hasSubAgents:!1,isSubAgent:!0,parentName}}}async function scanForAgentsAll(root,ignoreFilePath){let results=[];for await(let agent of scanForAgents(root,ignoreFilePath))results.push(agent);return results}init_workspace();async function discoverExternalAgents(workspaceRoot){let allScanned=await scanForAgentsAll(workspaceRoot),canonicalNames=new Set(scanAgents2(workspaceRoot)),agentsDir=join79(workspaceRoot,"agents"),external2=[];for(let scanned of allScanned){if(scanned.path.startsWith(agentsDir))continue;if(canonicalNames.has(scanned.dirName))continue;external2.push({name:scanned.dirName,path:scanned.path,relativePath:relative6(workspaceRoot,scanned.path),isSubAgent:scanned.isSubAgent,parentName:scanned.parentName})}return external2}function importAgents(workspaceRoot,agents){let agentsDir=join79(workspaceRoot,"agents");mkdirSync31(agentsDir,{recursive:!0});let result2={imported:[],skipped:[],errors:[]};for(let agent of agents){let destName=resolveUniqueName(agentsDir,agent.name),destPath=join79(agentsDir,destName);if(existsSync68(destPath)){result2.skipped.push(agent.name);continue}try{moveDirectory(agent.path,destPath),result2.imported.push(destName)}catch(err){result2.errors.push({name:agent.name,error:err instanceof Error?err.message:String(err)})}}return result2}function moveDirectory(src,dest){try{renameSync13(src,dest)}catch{cpSync(src,dest,{recursive:!0}),rmSync4(src,{recursive:!0,force:!0})}}function resolveUniqueName(agentsDir,name){if(!existsSync68(join79(agentsDir,name)))return name;let suffix=2;while(existsSync68(join79(agentsDir,`${name}-${suffix}`)))suffix++;return`${name}-${suffix}`}init_interactivity();init_defaults();import{readFileSync as readFileSync45,writeFileSync as writeFileSync29}from"fs";import{join as join80}from"path";function formatDefaults(workspaceDefaults){let effective=computeEffectiveDefaults(workspaceDefaults),lines=[];for(let key of Object.keys(BUILTIN_DEFAULTS)){let value=effective[key],source=workspaceDefaults?.[key]!==void 0?"workspace":"built-in";lines.push(` ${key}: ${value} (${source})`)}return lines.join(`
4411
4414
  `)}function formatWelcome(ctx){let lines=["",` Workspace: ${ctx.workspaceName}`,` Agents: ${ctx.canonicalAgentCount} registered`];if(ctx.discovered.length>0)lines.push(` Discovered: ${ctx.discovered.length} external agent(s) found`);return lines.push(""),lines.push(" Effective defaults:"),lines.push(formatDefaults(ctx.config.agents?.defaults)),lines.push(""),lines.join(`
4412
4415
  `)}function formatNextSteps(ctx){let lines=[""," Next steps:"];if(ctx.canonicalAgentCount===0)lines.push(" genie init agent <name> Scaffold your first agent");return lines.push(" genie spawn <agent> Launch an agent"),lines.push(" genie team create <name> Create a multi-agent team"),lines.push(" /wizard Full guided onboarding"),lines.push(""),lines.join(`
4413
4416
  `)}var MODEL_CHOICES=[{name:"opus (most capable)",value:"opus"},{name:"sonnet (balanced)",value:"sonnet"},{name:"haiku (fastest)",value:"haiku"}];async function runMiniWizard(ctx){let{confirm:confirm3}=await Promise.resolve().then(() => (init_esm14(),exports_esm));console.log(formatWelcome(ctx));let wantCustomize=await confirm3({message:"Customize workspace defaults?",default:!1}),result2={customized:!1,importedAgents:[],completed:!0};if(wantCustomize){let newDefaults=await customizeDefaults(ctx.config.agents?.defaults);if(newDefaults)result2.customized=!0,result2.defaults=newDefaults,persistDefaults(ctx.workspaceRoot,newDefaults)}if(ctx.pending.length>0){console.log(`
@@ -4426,7 +4429,7 @@ Event Throughput (last 60s):`),console.log(` Emitted: ${data.events_emitted_la
4426
4429
  ORDER BY created_at ASC
4427
4430
  `;if(options.json){console.log(JSON.stringify(rows,null,2));return}if(rows.length===0){console.log("No snapshots in the given time range.");return}let headers=["Time","Workers","Teams","Tmux","CPU%","Mem MB"],data=rows.map((r)=>[formatRelativeTimestamp(r.created_at),String(r.active_workers??0),String(r.active_teams??0),String(r.tmux_sessions??0),r.cpu_percent!==null?String(r.cpu_percent):"-",r.memory_mb!==null?String(r.memory_mb):"-"]),widths=headers.map((h,i2)=>{let colVals=data.map((row2)=>row2[i2]);return Math.max(h.length,...colVals.map((v)=>v.length))});console.log(headers.map((h,i2)=>padRight(h,widths[i2])).join(" | ")),console.log(widths.map((w)=>"-".repeat(w)).join("-+-"));for(let row2 of data)console.log(row2.map((v,i2)=>padRight(v,widths[i2])).join(" | "));console.log(`
4428
4431
  (${rows.length} snapshot${rows.length===1?"":"s"})`)}async function metricsAgentsCommand(options){if(options.json){console.log(JSON.stringify({deprecated:!0,replacement:"genie status",message:"Use `genie status` for live agent state."}));return}console.error("\u26A0\uFE0F `genie metrics agents` is deprecated and will be removed in a future release."),console.error(" Use `genie status` for live agent state.")}function registerMetricsCommands(program2){let metrics=program2.command("metrics").description("Machine metrics \u2014 snapshots, heartbeats, agents");metrics.command("now",{isDefault:!0}).description("Current machine state").option("--json","Output as JSON").action(async(options)=>{await metricsNowCommand(options)}),metrics.command("history").description("Machine snapshot history").option("--since <duration>","Time window (e.g., 1h, 6h, 1d)","1h").option("--json","Output as JSON").action(async(options)=>{await metricsHistoryCommand(options)}),metrics.command("agents").description("[DEPRECATED] Use `genie status` for live agent state").option("--json","Output as JSON").action(async(options)=>{await metricsAgentsCommand(options)})}init_msg();init_term_format();var _taskService4;async function getTaskService4(){if(!_taskService4)_taskService4=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService4}function currentActor2(){return{actorType:"local",actorId:process.env.GENIE_AGENT_NAME??"cli"}}async function handleNotifySet(options){let ts3=await getTaskService4(),actor=currentActor2(),pref=await ts3.setPreference(actor,options.channel,{priorityThreshold:options.priority,isDefault:options.default}),defaultLabel=pref.isDefault?", default":"";console.log(`Notification preference set: ${pref.channel} (threshold: ${pref.priorityThreshold}${defaultLabel}).`)}function printPrefsTable(prefs){console.log(` ${padRight("CHANNEL",15)} ${padRight("THRESHOLD",12)} ${padRight("DEFAULT",10)} ENABLED`),console.log(` ${"\u2500".repeat(45)}`);for(let p of prefs){let dflt=p.isDefault?"yes":"no",enabled=p.enabled?"yes":"no";console.log(` ${padRight(p.channel,15)} ${padRight(p.priorityThreshold,12)} ${padRight(dflt,10)} ${enabled}`)}console.log(`
4429
- ${prefs.length} preference${prefs.length===1?"":"s"}`)}async function handleNotifyList(options){let ts3=await getTaskService4(),actor=currentActor2(),prefs=await ts3.getPreferences(actor);if(options.json){console.log(JSON.stringify(prefs,null,2));return}if(prefs.length===0){console.log("No notification preferences configured.");return}printPrefsTable(prefs)}async function handleNotifyRemove(options){let ts3=await getTaskService4(),actor=currentActor2();if(await ts3.deletePreference(actor,options.channel))console.log(`Removed notification preference for channel: ${options.channel}`);else console.log(`No preference found for channel: ${options.channel}`)}function registerNotifyCommands(program2){let notify=program2.command("notify").description("Notification preference management");notify.command("set").description("Set notification preference for a channel").requiredOption("--channel <channel>","Channel: whatsapp, telegram, email, slack, discord, tmux").option("--priority <priority>","Minimum priority threshold","normal").option("--default","Set as default channel").action(async(options)=>{try{await handleNotifySet(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),notify.command("list").description("List notification preferences").option("--json","Output as JSON").action(async(options)=>{try{await handleNotifyList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),notify.command("remove").description("Remove a notification preference").requiredOption("--channel <channel>","Channel to remove").action(async(options)=>{try{await handleNotifyRemove(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_agent_observability();init_term_format();var FLAG_LABELS2={stale_executor:"STALE",missing_session:"NO-SESSION",missing_attribution:"UNATTRIBUTED",high_hook_latency:"SLOW-HOOK",recent_failure:"TOOL-ERR",cost_spike:"COST"};function summarize(snap){let name=snap.customName??snap.role??snap.agentId,namePart=padRight(truncate2(name,28),28),exec3=snap.executorState??"-",execPart=padRight(truncate2(exec3,12),12),tools=`${snap.recentToolCount} tools / ${snap.recentErrorCount} err`,cost=snap.recentCostUsd>0?`$${snap.recentCostUsd.toFixed(2)}`:"$0",last=snap.recentLastToolAt?formatRelativeTimestamp(snap.recentLastToolAt):"-",health=snap.health.flags.length===0?color("green","OK"):color("yellow",snap.health.flags.map((f)=>FLAG_LABELS2[f]).join(","));return` ${namePart} ${execPart} ${padRight(tools,18)} ${padRight(cost,8)} last:${padRight(last,9)} ${health}`}function renderHumanFleet(snaps,includeHarness){if(console.log(""),console.log(color("bold",includeHarness?"AGENTS + HARNESS":"AGENTS")),console.log("-".repeat(72)),snaps.length===0){console.log(color("dim"," (none)")),console.log("");return}for(let snap of snaps)console.log(summarize(snap));let degraded=snaps.filter((s2)=>s2.health.degraded).length;console.log(""),console.log(color("dim",` ${snaps.length} rows, ${degraded} degraded \u2014 schema v${AGENT_OBSERVABILITY_SCHEMA_VERSION}`)),console.log("")}async function observeAgentsCommand(opts={}){let limit=opts.limit?Number.parseInt(opts.limit,10):void 0,snaps=await listAgentObservability({includeHarness:opts.includeHarness===!0,limit:Number.isFinite(limit)?limit:void 0});if(opts.json)console.log(JSON.stringify({_source:{schemaVersion:AGENT_OBSERVABILITY_SCHEMA_VERSION,view:"v_agent_observability"},agents:snaps},null,2));else renderHumanFleet(snaps,opts.includeHarness===!0);if(opts.strict&&snaps.some((s2)=>s2.health.degraded))process.exit(1)}function registerObserveCommands(program2){let observe=program2.command("observe").description("Canonical observability snapshots");observe.command("agents").description("Fleet-level agent observability snapshot").option("--json","Emit machine-readable JSON").option("--include-harness","Include rows whose classification is `harness`").option("--strict","Exit with code 1 when any row is degraded").option("--limit <n>","Maximum rows to return").action(async(options)=>{try{await observeAgentsCommand(options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`observe: ${message}`),process.exit(2)}}),observe.on("command:*",(operands)=>{let cmd=operands[0],available=observe.commands.map((c)=>c.name()).join(", ");observe.error(`Unknown observe command '${cmd}'. Available: ${available}`)})}init_genie_config2();import{generateKeyPairSync}from"crypto";import{chmodSync as chmodSync4,existsSync as existsSync71,mkdirSync as mkdirSync34,readFileSync as readFileSync47,writeFileSync as writeFileSync32}from"fs";import{hostname as osHostname}from"os";import{dirname as dirname28,join as join83,resolve as resolvePath5}from"path";function keyPaths2(){let home=process.env.GENIE_HOME??join83(process.env.HOME??"/root",".genie"),dir=join83(home,"keys");return{dir,privateKey:join83(dir,"genie-host.ed25519"),publicKey:join83(dir,"genie-host.ed25519.pub"),hostJson:join83(dir,"host.json")}}function assertNotInsideGitRepo(dir){let probe=resolvePath5(dir);for(let depth=0;depth<16;depth++){if(existsSync71(join83(probe,".git")))throw Error(`Refusing to write keys to ${dir} \u2014 it lives inside a git working tree (${join83(probe,".git")}). Set $GENIE_HOME to a path outside any git repo and re-run.`);let parent=dirname28(probe);if(parent===probe)return;probe=parent}}function generateAndPersistKeypair(paths){if(!existsSync71(paths.dir))mkdirSync34(paths.dir,{recursive:!0,mode:448});let{publicKey,privateKey}=generateKeyPairSync("ed25519"),rawPub=publicKey.export({format:"der",type:"spki"}),pubkeyB64Url=rawPub.subarray(rawPub.length-32).toString("base64url");return writeFileSync32(paths.privateKey,privateKey.export({format:"pem",type:"pkcs8"}),{mode:384}),writeFileSync32(paths.publicKey,pubkeyB64Url,{mode:420}),chmodSync4(paths.privateKey,384),{pubkeyB64Url}}function loadExistingPubkey(paths){if(!existsSync71(paths.publicKey))return null;return readFileSync47(paths.publicKey,"utf-8").trim()}function loadHostJson(paths){if(!existsSync71(paths.hostJson))return null;try{return JSON.parse(readFileSync47(paths.hostJson,"utf-8"))}catch{return null}}function writeHostJson(paths,record){writeFileSync32(paths.hostJson,`${JSON.stringify(record,null,2)}
4432
+ ${prefs.length} preference${prefs.length===1?"":"s"}`)}async function handleNotifyList(options){let ts3=await getTaskService4(),actor=currentActor2(),prefs=await ts3.getPreferences(actor);if(options.json){console.log(JSON.stringify(prefs,null,2));return}if(prefs.length===0){console.log("No notification preferences configured.");return}printPrefsTable(prefs)}async function handleNotifyRemove(options){let ts3=await getTaskService4(),actor=currentActor2();if(await ts3.deletePreference(actor,options.channel))console.log(`Removed notification preference for channel: ${options.channel}`);else console.log(`No preference found for channel: ${options.channel}`)}function registerNotifyCommands(program2){let notify=program2.command("notify").description("Notification preference management");notify.command("set").description("Set notification preference for a channel").requiredOption("--channel <channel>","Channel: whatsapp, telegram, email, slack, discord, tmux").option("--priority <priority>","Minimum priority threshold","normal").option("--default","Set as default channel").action(async(options)=>{try{await handleNotifySet(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),notify.command("list").description("List notification preferences").option("--json","Output as JSON").action(async(options)=>{try{await handleNotifyList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),notify.command("remove").description("Remove a notification preference").requiredOption("--channel <channel>","Channel to remove").action(async(options)=>{try{await handleNotifyRemove(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_agent_observability();init_term_format();var FLAG_LABELS2={stale_executor:"STALE",missing_session:"NO-SESSION",missing_attribution:"UNATTRIBUTED",high_hook_latency:"SLOW-HOOK",recent_failure:"TOOL-ERR",cost_spike:"COST"};function summarize(snap){let name=snap.customName??snap.role??snap.agentId,namePart=padRight(truncate2(name,28),28),exec3=snap.executorState??"-",execPart=padRight(truncate2(exec3,12),12),tools=`${snap.recentToolCount} tools / ${snap.recentErrorCount} err`,cost=snap.recentCostUsd>0?`$${snap.recentCostUsd.toFixed(2)}`:"$0",last=snap.recentLastToolAt?formatRelativeTimestamp(snap.recentLastToolAt):"-",health=snap.health.flags.length===0?color("green","OK"):color("yellow",snap.health.flags.map((f)=>FLAG_LABELS2[f]).join(","));return` ${namePart} ${execPart} ${padRight(tools,18)} ${padRight(cost,8)} last:${padRight(last,9)} ${health}`}function renderHumanFleet(snaps,includeHarness){if(console.log(""),console.log(color("bold",includeHarness?"AGENTS + HARNESS":"AGENTS")),console.log("-".repeat(72)),snaps.length===0){console.log(color("dim"," (none)")),console.log("");return}for(let snap of snaps)console.log(summarize(snap));let degraded=snaps.filter((s2)=>s2.health.degraded).length;console.log(""),console.log(color("dim",` ${snaps.length} rows, ${degraded} degraded \u2014 schema v${AGENT_OBSERVABILITY_SCHEMA_VERSION}`)),console.log("")}async function observeAgentsCommand(opts={}){let limit=opts.limit?Number.parseInt(opts.limit,10):void 0,snaps=await listAgentObservability({includeHarness:opts.includeHarness===!0,limit:Number.isFinite(limit)?limit:void 0});if(opts.json)console.log(JSON.stringify({_source:{schemaVersion:AGENT_OBSERVABILITY_SCHEMA_VERSION,view:"v_agent_observability"},agents:snaps},null,2));else renderHumanFleet(snaps,opts.includeHarness===!0);if(opts.strict&&snaps.some((s2)=>s2.health.degraded))process.exit(1)}function registerObserveCommands(program2){let observe=program2.command("observe").description("Canonical observability snapshots");observe.command("agents").description("Fleet-level agent observability snapshot").option("--json","Emit machine-readable JSON").option("--include-harness","Include rows whose classification is `harness`").option("--strict","Exit with code 1 when any row is degraded").option("--limit <n>","Maximum rows to return").action(async(options)=>{try{await observeAgentsCommand(options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`observe: ${message}`),process.exit(2)}}),observe.on("command:*",(operands)=>{let cmd=operands[0],available=observe.commands.map((c)=>c.name()).join(", ");observe.error(`Unknown observe command '${cmd}'. Available: ${available}`)})}init_genie_config2();import{generateKeyPairSync}from"crypto";import{chmodSync as chmodSync4,existsSync as existsSync71,mkdirSync as mkdirSync34,readFileSync as readFileSync47,writeFileSync as writeFileSync32}from"fs";import{hostname as osHostname}from"os";import{dirname as dirname29,join as join83,resolve as resolvePath5}from"path";function keyPaths2(){let home=process.env.GENIE_HOME??join83(process.env.HOME??"/root",".genie"),dir=join83(home,"keys");return{dir,privateKey:join83(dir,"genie-host.ed25519"),publicKey:join83(dir,"genie-host.ed25519.pub"),hostJson:join83(dir,"host.json")}}function assertNotInsideGitRepo(dir){let probe=resolvePath5(dir);for(let depth=0;depth<16;depth++){if(existsSync71(join83(probe,".git")))throw Error(`Refusing to write keys to ${dir} \u2014 it lives inside a git working tree (${join83(probe,".git")}). Set $GENIE_HOME to a path outside any git repo and re-run.`);let parent=dirname29(probe);if(parent===probe)return;probe=parent}}function generateAndPersistKeypair(paths){if(!existsSync71(paths.dir))mkdirSync34(paths.dir,{recursive:!0,mode:448});let{publicKey,privateKey}=generateKeyPairSync("ed25519"),rawPub=publicKey.export({format:"der",type:"spki"}),pubkeyB64Url=rawPub.subarray(rawPub.length-32).toString("base64url");return writeFileSync32(paths.privateKey,privateKey.export({format:"pem",type:"pkcs8"}),{mode:384}),writeFileSync32(paths.publicKey,pubkeyB64Url,{mode:420}),chmodSync4(paths.privateKey,384),{pubkeyB64Url}}function loadExistingPubkey(paths){if(!existsSync71(paths.publicKey))return null;return readFileSync47(paths.publicKey,"utf-8").trim()}function loadHostJson(paths){if(!existsSync71(paths.hostJson))return null;try{return JSON.parse(readFileSync47(paths.hostJson,"utf-8"))}catch{return null}}function writeHostJson(paths,record){writeFileSync32(paths.hostJson,`${JSON.stringify(record,null,2)}
4430
4433
  `,{mode:420})}async function resolveOmniApiKey2(){let envKey=process.env.OMNI_API_KEY;if(envKey)return envKey;return(await loadGenieConfig()).omni?.apiKey}async function callTrustEndpoint(apiUrl,apiKey,method,path3,body){let headers={"Content-Type":"application/json"};if(apiKey)headers.Authorization=`Bearer ${apiKey}`;let res=await fetch(`${apiUrl.replace(/\/+$/,"")}/api/v2/trust${path3}`,{method,headers,body:body===void 0?void 0:JSON.stringify(body)});if(!res.ok){let text=await res.text().catch(()=>"");throw Error(`omni trust ${method} ${path3}: HTTP ${res.status}${text?` \u2014 ${text}`:""}`)}return await res.json()}async function handleHandshake(options){let apiUrl=await resolveOmniApiUrl();if(!apiUrl)throw Error("Omni is not configured. Set OMNI_API_URL or `omni.apiUrl` in your genie config first.\nExample: omni install");let apiKey=await resolveOmniApiKey2();if(!apiKey)throw Error("Omni API key not configured. Set OMNI_API_KEY or `omni.apiKey` in your genie config.");let paths=keyPaths2();assertNotInsideGitRepo(paths.dir);let previousRecord=loadHostJson(paths),pubkey=loadExistingPubkey(paths);if(options.rotate){if(!previousRecord)throw Error("Cannot --rotate: no existing host record at ~/.genie/keys/host.json. Run a plain handshake first.");pubkey=generateAndPersistKeypair(paths).pubkeyB64Url}else if(!pubkey)pubkey=generateAndPersistKeypair(paths).pubkeyB64Url;let hostname2=options.hostname??previousRecord?.hostname??osHostname()??"unknown-host",capabilities={genieVersion:process.env.GENIE_VERSION??"unknown",platform:process.platform,nodeVersion:process.version},{data:host}=await callTrustEndpoint(apiUrl,apiKey,"POST","/handshake",{pubkey,hostname:hostname2,capabilities}),newRecord={hostId:host.id,pubkey:host.pubkey,hostname:host.hostname,registeredAt:new Date().toISOString(),...options.rotate&&previousRecord?{rotatedFrom:previousRecord.hostId}:{}};if(writeHostJson(paths,newRecord),options.rotate&&previousRecord&&previousRecord.hostId!==host.id)try{await callTrustEndpoint(apiUrl,apiKey,"DELETE",`/hosts/${previousRecord.hostId}`)}catch(err){let message=err instanceof Error?err.message:String(err);console.warn(`
4431
4434
  \u26A0 Rotated key registered as ${host.id}, but revoking the old host (${previousRecord.hostId}) failed:
4432
4435
  ${message}
@@ -4436,8 +4439,8 @@ Event Throughput (last 60s):`),console.log(` Emitted: ${data.events_emitted_la
4436
4439
  Project: ${p.name}`),console.log("\u2500".repeat(50)),console.log(` ID: ${p.id}`),console.log(` Type: ${p.repoPath?"repo":"virtual"}`),p.repoPath)console.log(` Path: ${p.repoPath}`);if(p.description)console.log(` Desc: ${p.description}`);if(console.log(` Created: ${formatDate(p.createdAt)}`),console.log(` Tasks: ${tasks.length}`),tasks.length>0){console.log(`
4437
4440
  By status:`);for(let[status2,count]of Object.entries(byStatus).sort())console.log(` ${padRight(status2,15)} ${count}`);console.log(`
4438
4441
  By stage:`);for(let[stage,count]of Object.entries(byStage).sort())console.log(` ${padRight(stage,15)} ${count}`)}}function registerProjectCommands(program2){let project=program2.command("project").description("Project management \u2014 named task boards");project.command("list").description("List all projects").option("--all","Include archived projects").option("--json","Output as JSON").action(async(options)=>{try{let ts3=await getTaskService5(),projects=await ts3.listProjectsFiltered(options.all);if(options.json){console.log(JSON.stringify(projects,null,2));return}if(projects.length===0){console.log("No projects found. Projects are auto-created when you run `genie task create`.");return}await printProjectList(ts3,projects)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),project.command("create <name>").description("Create a new project").option("--virtual","Create a virtual project (not tied to a repo)").option("--repo <path>","Repo path for the project").option("--description <text>","Project description").action(async(name,options)=>{try{let ts3=await getTaskService5(),repoPath=options.virtual?null:options.repo??null,p=await ts3.createProject({name,repoPath,description:options.description});if(console.log(`Created project "${p.name}"`),console.log(` ID: ${p.id}`),console.log(` Type: ${p.repoPath?"repo":"virtual"}`),p.repoPath)console.log(` Path: ${p.repoPath}`);if(p.description)console.log(` Desc: ${p.description}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),project.command("show <name>").description("Show project detail with task stats").option("--json","Output as JSON").action(async(name,options)=>{try{let ts3=await getTaskService5(),p=await ts3.getProjectByName(name);if(!p){console.error(`Error: Project not found: ${name}`),process.exit(1);return}if(options.json){console.log(JSON.stringify(p,null,2));return}let tasks=await ts3.listTasks({projectName:name,allProjects:!0});printProjectDetail(p,tasks)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),project.command("archive <name>").description("Archive a project (cascades to boards and unfinished tasks)").action(async(name)=>{try{await(await getTaskService5()).archiveProject(name),console.log(`Archived project "${name}" and cascaded to boards + unfinished tasks.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),project.command("unarchive <name>").description("Restore an archived project and its boards (tasks stay as-is)").action(async(name)=>{try{await(await getTaskService5()).unarchiveProject(name),console.log(`Unarchived project "${name}" and restored boards.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),project.command("set-default <name>").description("Set default project for when outside any repo").action(async(name)=>{try{if(!await(await getTaskService5()).getProjectByName(name))console.error(`Error: Project not found: ${name}`),process.exit(1);let{loadGenieConfig:loadGenieConfig2,saveGenieConfig:saveGenieConfig2}=await Promise.resolve().then(() => (init_genie_config2(),exports_genie_config)),config=await loadGenieConfig2();config.defaultProject=name,await saveGenieConfig2(config),console.log(`Default project set to "${name}"`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_agent_registry();init_db();var DEFAULT_TTL_HOURS={zombies:24,errored:1},TARGET_LABEL={zombies:"zombie agent",errored:"errored agent"};function parsePositiveInt(value,name){let parsed=Number.parseInt(value,10);if(!Number.isFinite(parsed)||parsed<=0)throw Error(`Invalid ${name}: ${value} (expected a positive integer)`);return parsed}async function listTargets(mode,ttlHours){return mode==="zombies"?listExhaustedZombies(ttlHours):listAllExhaustedErrored(ttlHours)}async function archiveTargets(mode,ttlHours){return mode==="zombies"?archiveExhaustedZombies(ttlHours):archiveAllExhaustedErrored(ttlHours)}async function runDryRun(mode,ttlHours){let rows=await listTargets(mode,ttlHours);if(rows.length===0){console.log(`No exhausted ${TARGET_LABEL[mode]}s older than ${ttlHours}h.`);return}let plural=rows.length===1?"":"s";console.log(`Would archive ${rows.length} ${TARGET_LABEL[mode]}${plural} older than ${ttlHours}h:`);for(let r of rows)console.log(` ${r.id} (last state change: ${r.lastStateChange})`)}async function runArchive(mode,ttlHours){let ids=await archiveTargets(mode,ttlHours);if(ids.length===0){console.log(`No exhausted ${TARGET_LABEL[mode]}s older than ${ttlHours}h. Nothing to archive.`);return}let plural=ids.length===1?"":"s";console.log(`Archived ${ids.length} ${TARGET_LABEL[mode]}${plural} older than ${ttlHours}h:`);for(let id of ids)console.log(` ${id}`)}function resolveMode(options){if(options.zombies&&options.errored)console.error("Error: --zombies and --errored are mutually exclusive."),process.exit(2);if(options.zombies)return"zombies";if(options.errored)return"errored";console.error("Error: no prune target specified. Use `--zombies` or `--errored`."),console.error("See `genie prune --help` for available targets."),process.exit(2)}async function pruneCommand(options){let mode=resolveMode(options),ttlHours=options.ttlHours??DEFAULT_TTL_HOURS[mode];if(!await isAvailable())console.error("Database is not running. Start it with: genie db status"),process.exit(1);try{await(options.dryRun?runDryRun(mode,ttlHours):runArchive(mode,ttlHours))}catch(err){let message=err instanceof Error?err.message:String(err);console.error(`Prune failed: ${message}`),process.exit(1)}finally{await shutdown().catch(()=>{})}}function registerPruneCommands(program2){program2.command("prune").description("Bulk cleanup of stale or exhausted registry entries").option("--zombies","Archive reconciler-tagged dead-pane zombies (24h default TTL)").option("--errored","Archive any exhausted error-state agent regardless of reason (1h default TTL; set auto_resume=true to keep a row visible)").option("--dry-run","List targets that would be affected without mutating").option("--ttl-hours <hours>","Override the mode default TTL in hours (24 for --zombies, 1 for --errored)",(v)=>parsePositiveInt(v,"--ttl-hours")).action(pruneCommand)}init_agent_registry();import{readFile as readFile16,stat as stat10}from"fs/promises";import{join as join86}from"path";import{readFile as readFile14}from"fs/promises";async function parseQaSpec(filePath){let content=await readFile14(filePath,"utf-8");return parseQaSpecContent(content,filePath)}var SECTION_MAP={setup:"setup",actions:"actions",expect:"expect"};function detectSection(line){for(let[keyword,section]of Object.entries(SECTION_MAP))if(new RegExp(`^##\\s+${keyword}`,"i").test(line))return section;if(line.startsWith("## "))return"none";return null}function parseQaSpecContent(content,filePath="<inline>"){let lines=content.split(`
4439
- `),name="",currentSection="none",setup=[],actions=[],expect=[],parsers2={none:()=>{},setup:(line)=>{let step=parseSetupLine(line);if(step)setup.push(step)},actions:(line)=>{let step=parseActionLine(line);if(step)actions.push(step)},expect:(line)=>{let exp=parseExpectLine(line);if(exp)expect.push(exp)}};for(let line of lines){let trimmed=line.trim();if(trimmed.startsWith("# ")&&!trimmed.startsWith("## ")){let match=trimmed.match(/^#\s+(?:Test:\s*)?(.+)$/);if(match)name=match[1].trim();continue}let section=detectSection(trimmed);if(section!==null){currentSection=section;continue}if(!trimmed||trimmed.startsWith("//")||trimmed.startsWith("<!--"))continue;parsers2[currentSection](trimmed)}if(!name)name=filePath.replace(/.*\//,"").replace(/\.md$/,"");return{name,file:filePath,setup,actions,expect}}function parseSetupLine(line){let text=stripListPrefix(line);if(!text)return null;let spawnMatch=text.match(/^spawn\s+(\S+)(?:\s+\((.+)\))?$/i);if(spawnMatch)return{kind:"spawn",target:spawnMatch[1],options:spawnMatch[2]?parseOptions2(spawnMatch[2]):{}};let followMatch=text.match(/^(?:start\s+)?follow(?:\s+(?:on\s+)?(\S+))?(?:\s+\((.+)\))?$/i);if(followMatch)return{kind:"follow",target:followMatch[1]||"team",options:followMatch[2]?parseOptions2(followMatch[2]):{}};return null}function parseActionLine(line){let text=stripListPrefix(line);if(!text)return null;let sendMatch=text.match(/^send\s+"([^"]+)"\s+to\s+(\S+)/i);if(sendMatch)return{kind:"send",message:sendMatch[1],to:sendMatch[2]};let waitMatch=text.match(/^wait\s+(?:for\s+.+?\s+)?\(?(?:max\s+)?(\d+)s\)?/i);if(waitMatch)return{kind:"wait",seconds:Number.parseInt(waitMatch[1],10)};let runMatch=text.match(/^run\s+(.+)$/i);if(runMatch)return{kind:"run",command:runMatch[1]};return null}function detectSource(text){if(/\binbox\b/i.test(text))return"inbox";if(/\blog\b/i.test(text))return"log";if(/\boutput\b/i.test(text))return"output";return"log"}function extractMatchers(text){let matchers={},matcherRegex=/(\w+)\s*([~!]?=)\s*(?:"([^"]+)"|(\S+))/g;for(let match of text.matchAll(matcherRegex)){let op=match[2]==="~="?"~":"",value=(match[3]??match[4]).trim();matchers[match[1]]=`${op}${value}`}return matchers}function parseExpectLine(line){let text=line.replace(/^[-*]\s*\[[ x]\]\s*/i,"").trim();if(!text)return null;return{description:text,source:detectSource(text),matchers:extractMatchers(text)}}function stripListPrefix(line){return line.replace(/^[-*]\s+/,"").replace(/^\d+\.\s+/,"").trim()}function parseOptions2(text){let opts={};for(let pair of text.split(",")){let[key,...rest]=pair.split(":");if(key&&rest.length>0)opts[key.trim()]=rest.join(":").trim()}return opts}import{cp as cp2,mkdir as mkdir11,rm as rm3,writeFile as writeFile10}from"fs/promises";import{tmpdir as tmpdir4}from"os";import{dirname as dirname29,join as join85,resolve as resolve18}from"path";var{$:$4}=globalThis.Bun;import{createHash as createHash9}from"crypto";import{mkdir as mkdir10,readFile as readFile15,readdir as readdir10,stat as stat9,writeFile as writeFile9}from"fs/promises";import{homedir as homedir50}from"os";import{join as join84,relative as relative8,resolve as resolve17}from"path";function repoHash(repoPath){return createHash9("sha256").update(resolve17(repoPath)).digest("hex").slice(0,12)}function resultsDir(repoPath){let base=process.env.GENIE_HOME??join84(homedir50(),".genie");return join84(base,"qa",repoHash(repoPath))}function resultsPath(repoPath){return join84(resultsDir(repoPath),"results.json")}async function loadResults(repoPath){try{let raw=await readFile15(resultsPath(repoPath),"utf-8");return JSON.parse(raw)}catch{return{}}}async function saveResult(repoPath,specKey,report2){let dir=resultsDir(repoPath);await mkdir10(dir,{recursive:!0});let results=await loadResults(repoPath),specHash=await hashSpecFile(report2.file);results[specKey]={lastRun:new Date().toISOString(),result:report2.result,durationMs:report2.durationMs,specHash,expectations:report2.expectations,error:report2.error},await writeFile9(resultsPath(repoPath),JSON.stringify(results,null,2))}async function isStale(repoPath,specKey,specFilePath){let stored=(await loadResults(repoPath))[specKey];if(!stored)return!1;return await hashSpecFile(specFilePath)!==stored.specHash}async function listAllSpecs(specDir){let entries=[];return await walkSpecs(specDir,specDir,entries),entries.sort((a,b2)=>{if(a.domain!==b2.domain)return a.domain.localeCompare(b2.domain);return a.name.localeCompare(b2.name)})}async function hashSpecFile(filePath){try{let content=await readFile15(filePath,"utf-8");return createHash9("sha256").update(content).digest("hex").slice(0,12)}catch{return"unknown"}}async function walkSpecs(baseDir,dir,entries){let items=await readdir10(dir);for(let item of items){let fullPath=join84(dir,item);if((await stat9(fullPath)).isDirectory())await walkSpecs(baseDir,fullPath,entries);else if(item.endsWith(".md")){let rel=relative8(baseDir,fullPath),parts=rel.replace(/\.md$/,"").split("/"),domain=parts.length>1?parts.slice(0,-1).join("/"):"(root)",name=parts[parts.length-1];entries.push({key:rel.replace(/\.md$/,""),domain,name,filePath:fullPath})}}}function specKeyFromPath(specDir,filePath){return relative8(specDir,filePath).replace(/\.md$/,"")}function formatTimeAgo(isoDate){let ms=Date.now()-new Date(isoDate).getTime(),seconds=Math.floor(ms/1000);if(seconds<60)return`${seconds}s ago`;let minutes=Math.floor(seconds/60);if(minutes<60)return`${minutes}m ago`;let hours=Math.floor(minutes/60);if(hours<24)return`${hours}h ago`;return`${Math.floor(hours/24)}d ago`}init_runtime_events();init_team_manager();function emitNdjson(event){process.stdout.write(`${JSON.stringify(event)}
4440
- `)}async function publishQaEvent(repoPath,qaType,payload){let{specKey,domain,team,...rest}=payload;await publishSubjectEvent(repoPath,`genie.qa.${qaType}`,{kind:"qa",agent:"qa",team,text:`${qaType}: ${specKey}`,data:{qaType,specKey,domain,...rest},source:"hook"})}async function emitQaEvent(repoPath,qaType,payload,ndjson){if(await publishQaEvent(repoPath,qaType,payload),ndjson)emitNdjson(payload)}function parseStatusEntry(status2,parts,index){if(status2.startsWith("R")){let from=parts[index]??"",to=parts[index+1]??"";if(from&&to)return{op:{kind:"rename",from,to},nextIndex:index+2};return{op:null,nextIndex:index+2}}let path3=parts[index]??"";if(!path3)return{op:null,nextIndex:index+1};return{op:{kind:status2.startsWith("D")?"delete":"copy",path:path3},nextIndex:index+1}}function parseNameStatusZ(output){if(!output)return[];let parts=output.split("\x00").filter(Boolean),ops=[],i2=0;while(i2<parts.length){let status2=parts[i2++]??"";if(!status2)break;let{op,nextIndex}=parseStatusEntry(status2,parts,i2);if(i2=nextIndex,op)ops.push(op)}return ops}async function overlayDirtyWorkingTree(repoPath,worktreePath){let tracked=(await $4`git -C ${repoPath} diff --name-status --find-renames -z HEAD --`.quiet().nothrow().text()).trim(),untracked=(await $4`git -C ${repoPath} ls-files --others --exclude-standard -z`.quiet().nothrow().text()).trim(),ops=parseNameStatusZ(tracked);for(let path3 of untracked.split("\x00").filter(Boolean))ops.push({kind:"copy",path:path3});for(let op of ops){if(op.kind==="delete"){await rm3(join85(worktreePath,op.path),{recursive:!0,force:!0});continue}if(op.kind==="rename"){await rm3(join85(worktreePath,op.from),{recursive:!0,force:!0});let src2=join85(repoPath,op.to),dest2=join85(worktreePath,op.to);await mkdir11(dirname29(dest2),{recursive:!0}),await cp2(src2,dest2,{recursive:!0,force:!0});continue}let src=join85(repoPath,op.path),dest=join85(worktreePath,op.path);await mkdir11(dirname29(dest),{recursive:!0}),await cp2(src,dest,{recursive:!0,force:!0})}}async function runAllSpecs(specDir,options){let entries=await listAllSpecs(specDir);return runSpecEntries(entries,specDir,options)}async function runDomainSpecs(specDir,domain,options){let filtered=(await listAllSpecs(specDir)).filter((e)=>e.domain===domain);return runSpecEntries(filtered,specDir,options)}async function prepareTeams(entries,repoPath,ndjson){let prepared=[];console.error(`
4442
+ `),name="",currentSection="none",setup=[],actions=[],expect=[],parsers2={none:()=>{},setup:(line)=>{let step=parseSetupLine(line);if(step)setup.push(step)},actions:(line)=>{let step=parseActionLine(line);if(step)actions.push(step)},expect:(line)=>{let exp=parseExpectLine(line);if(exp)expect.push(exp)}};for(let line of lines){let trimmed=line.trim();if(trimmed.startsWith("# ")&&!trimmed.startsWith("## ")){let match=trimmed.match(/^#\s+(?:Test:\s*)?(.+)$/);if(match)name=match[1].trim();continue}let section=detectSection(trimmed);if(section!==null){currentSection=section;continue}if(!trimmed||trimmed.startsWith("//")||trimmed.startsWith("<!--"))continue;parsers2[currentSection](trimmed)}if(!name)name=filePath.replace(/.*\//,"").replace(/\.md$/,"");return{name,file:filePath,setup,actions,expect}}function parseSetupLine(line){let text=stripListPrefix(line);if(!text)return null;let spawnMatch=text.match(/^spawn\s+(\S+)(?:\s+\((.+)\))?$/i);if(spawnMatch)return{kind:"spawn",target:spawnMatch[1],options:spawnMatch[2]?parseOptions2(spawnMatch[2]):{}};let followMatch=text.match(/^(?:start\s+)?follow(?:\s+(?:on\s+)?(\S+))?(?:\s+\((.+)\))?$/i);if(followMatch)return{kind:"follow",target:followMatch[1]||"team",options:followMatch[2]?parseOptions2(followMatch[2]):{}};return null}function parseActionLine(line){let text=stripListPrefix(line);if(!text)return null;let sendMatch=text.match(/^send\s+"([^"]+)"\s+to\s+(\S+)/i);if(sendMatch)return{kind:"send",message:sendMatch[1],to:sendMatch[2]};let waitMatch=text.match(/^wait\s+(?:for\s+.+?\s+)?\(?(?:max\s+)?(\d+)s\)?/i);if(waitMatch)return{kind:"wait",seconds:Number.parseInt(waitMatch[1],10)};let runMatch=text.match(/^run\s+(.+)$/i);if(runMatch)return{kind:"run",command:runMatch[1]};return null}function detectSource(text){if(/\binbox\b/i.test(text))return"inbox";if(/\blog\b/i.test(text))return"log";if(/\boutput\b/i.test(text))return"output";return"log"}function extractMatchers(text){let matchers={},matcherRegex=/(\w+)\s*([~!]?=)\s*(?:"([^"]+)"|(\S+))/g;for(let match of text.matchAll(matcherRegex)){let op=match[2]==="~="?"~":"",value=(match[3]??match[4]).trim();matchers[match[1]]=`${op}${value}`}return matchers}function parseExpectLine(line){let text=line.replace(/^[-*]\s*\[[ x]\]\s*/i,"").trim();if(!text)return null;return{description:text,source:detectSource(text),matchers:extractMatchers(text)}}function stripListPrefix(line){return line.replace(/^[-*]\s+/,"").replace(/^\d+\.\s+/,"").trim()}function parseOptions2(text){let opts={};for(let pair of text.split(",")){let[key,...rest]=pair.split(":");if(key&&rest.length>0)opts[key.trim()]=rest.join(":").trim()}return opts}import{cp as cp2,mkdir as mkdir10,rm as rm3,writeFile as writeFile10}from"fs/promises";import{tmpdir as tmpdir4}from"os";import{dirname as dirname30,join as join85,resolve as resolve18}from"path";var{$:$4}=globalThis.Bun;import{createHash as createHash9}from"crypto";import{mkdir as mkdir9,readFile as readFile15,readdir as readdir10,stat as stat9,writeFile as writeFile9}from"fs/promises";import{homedir as homedir50}from"os";import{join as join84,relative as relative8,resolve as resolve17}from"path";function repoHash(repoPath){return createHash9("sha256").update(resolve17(repoPath)).digest("hex").slice(0,12)}function resultsDir(repoPath){let base=process.env.GENIE_HOME??join84(homedir50(),".genie");return join84(base,"qa",repoHash(repoPath))}function resultsPath(repoPath){return join84(resultsDir(repoPath),"results.json")}async function loadResults(repoPath){try{let raw=await readFile15(resultsPath(repoPath),"utf-8");return JSON.parse(raw)}catch{return{}}}async function saveResult(repoPath,specKey,report2){let dir=resultsDir(repoPath);await mkdir9(dir,{recursive:!0});let results=await loadResults(repoPath),specHash=await hashSpecFile(report2.file);results[specKey]={lastRun:new Date().toISOString(),result:report2.result,durationMs:report2.durationMs,specHash,expectations:report2.expectations,error:report2.error},await writeFile9(resultsPath(repoPath),JSON.stringify(results,null,2))}async function isStale(repoPath,specKey,specFilePath){let stored=(await loadResults(repoPath))[specKey];if(!stored)return!1;return await hashSpecFile(specFilePath)!==stored.specHash}async function listAllSpecs(specDir){let entries=[];return await walkSpecs(specDir,specDir,entries),entries.sort((a,b2)=>{if(a.domain!==b2.domain)return a.domain.localeCompare(b2.domain);return a.name.localeCompare(b2.name)})}async function hashSpecFile(filePath){try{let content=await readFile15(filePath,"utf-8");return createHash9("sha256").update(content).digest("hex").slice(0,12)}catch{return"unknown"}}async function walkSpecs(baseDir,dir,entries){let items=await readdir10(dir);for(let item of items){let fullPath=join84(dir,item);if((await stat9(fullPath)).isDirectory())await walkSpecs(baseDir,fullPath,entries);else if(item.endsWith(".md")){let rel=relative8(baseDir,fullPath),parts=rel.replace(/\.md$/,"").split("/"),domain=parts.length>1?parts.slice(0,-1).join("/"):"(root)",name=parts[parts.length-1];entries.push({key:rel.replace(/\.md$/,""),domain,name,filePath:fullPath})}}}function specKeyFromPath(specDir,filePath){return relative8(specDir,filePath).replace(/\.md$/,"")}function formatTimeAgo(isoDate){let ms=Date.now()-new Date(isoDate).getTime(),seconds=Math.floor(ms/1000);if(seconds<60)return`${seconds}s ago`;let minutes=Math.floor(seconds/60);if(minutes<60)return`${minutes}m ago`;let hours=Math.floor(minutes/60);if(hours<24)return`${hours}h ago`;return`${Math.floor(hours/24)}d ago`}init_runtime_events();init_team_manager();function emitNdjson(event){process.stdout.write(`${JSON.stringify(event)}
4443
+ `)}async function publishQaEvent(repoPath,qaType,payload){let{specKey,domain,team,...rest}=payload;await publishSubjectEvent(repoPath,`genie.qa.${qaType}`,{kind:"qa",agent:"qa",team,text:`${qaType}: ${specKey}`,data:{qaType,specKey,domain,...rest},source:"hook"})}async function emitQaEvent(repoPath,qaType,payload,ndjson){if(await publishQaEvent(repoPath,qaType,payload),ndjson)emitNdjson(payload)}function parseStatusEntry(status2,parts,index){if(status2.startsWith("R")){let from=parts[index]??"",to=parts[index+1]??"";if(from&&to)return{op:{kind:"rename",from,to},nextIndex:index+2};return{op:null,nextIndex:index+2}}let path3=parts[index]??"";if(!path3)return{op:null,nextIndex:index+1};return{op:{kind:status2.startsWith("D")?"delete":"copy",path:path3},nextIndex:index+1}}function parseNameStatusZ(output){if(!output)return[];let parts=output.split("\x00").filter(Boolean),ops=[],i2=0;while(i2<parts.length){let status2=parts[i2++]??"";if(!status2)break;let{op,nextIndex}=parseStatusEntry(status2,parts,i2);if(i2=nextIndex,op)ops.push(op)}return ops}async function overlayDirtyWorkingTree(repoPath,worktreePath){let tracked=(await $4`git -C ${repoPath} diff --name-status --find-renames -z HEAD --`.quiet().nothrow().text()).trim(),untracked=(await $4`git -C ${repoPath} ls-files --others --exclude-standard -z`.quiet().nothrow().text()).trim(),ops=parseNameStatusZ(tracked);for(let path3 of untracked.split("\x00").filter(Boolean))ops.push({kind:"copy",path:path3});for(let op of ops){if(op.kind==="delete"){await rm3(join85(worktreePath,op.path),{recursive:!0,force:!0});continue}if(op.kind==="rename"){await rm3(join85(worktreePath,op.from),{recursive:!0,force:!0});let src2=join85(repoPath,op.to),dest2=join85(worktreePath,op.to);await mkdir10(dirname30(dest2),{recursive:!0}),await cp2(src2,dest2,{recursive:!0,force:!0});continue}let src=join85(repoPath,op.path),dest=join85(worktreePath,op.path);await mkdir10(dirname30(dest),{recursive:!0}),await cp2(src,dest,{recursive:!0,force:!0})}}async function runAllSpecs(specDir,options){let entries=await listAllSpecs(specDir);return runSpecEntries(entries,specDir,options)}async function runDomainSpecs(specDir,domain,options){let filtered=(await listAllSpecs(specDir)).filter((e)=>e.domain===domain);return runSpecEntries(filtered,specDir,options)}async function prepareTeams(entries,repoPath,ndjson){let prepared=[];console.error(`
4441
4444
  [qa] Creating ${entries.length} teams...`);for(let entry2 of entries){let teamName=`qa-${Date.now().toString(36)}-${entry2.name.slice(0,8)}`;try{let spec=await parseQaSpec(entry2.filePath),config=await createTeam(teamName,repoPath);await overlayDirtyWorkingTree(repoPath,config.worktreePath),await hireAgent(teamName,"qa");let prompt2=buildTeamLeadPrompt(spec,teamName,repoPath),promptFile=join85(tmpdir4(),`genie-qa-${teamName}.md`);await writeFile10(promptFile,prompt2),prepared.push({entry:entry2,spec,teamName,worktreePath:config.worktreePath,promptFile}),console.error(` \u2713 ${entry2.name}`),await emitQaEvent(repoPath,"team-created",{type:"qa:team-created",specKey:entry2.key,domain:entry2.domain,team:teamName},ndjson)}catch(err){console.error(` \u2717 ${entry2.name}: ${err instanceof Error?err.message:err}`)}await new Promise((r)=>setTimeout(r,200))}return prepared}async function emitSpecDone(repoPath,specKey,domain,team,report2,ndjson){await emitQaEvent(repoPath,"spec-done",{type:"qa:spec-done",specKey,domain,team,result:report2.result,durationMs:report2.durationMs,expectations:report2.expectations,error:report2.error},ndjson)}async function runSpecEntries(entries,specDir,options){let repoPath=resolve18(options?.repoPath??process.cwd()),maxConcurrency=options?.parallel??5,timeoutMs=(options?.timeout??3600)*1000,ndjson=options?.ndjson??!1,GREEN="\x1B[32m",RED="\x1B[31m",RESET2="\x1B[0m",DIM2="\x1B[90m",prepared=await prepareTeams(entries,repoPath,ndjson);if(prepared.length===0)return[];let timelineSub=await followRuntimeEvents({repoPath,teamPrefix:"qa-"},(event)=>{if(!event?.timestamp||!event?.kind)return;let team=event.team??"";if(!team.startsWith("qa-"))return;let match=prepared.find((p)=>p.teamName===team),specKey=match?.entry.key??team,specName=match?.entry.name??team,domain=match?.entry.domain??"",time=new Date(event.timestamp).toLocaleTimeString("en-US",{hour12:!1}),text=(event.text??"").slice(0,100);if(console.error(` \x1B[90m${time}\x1B[0m \x1B[90m[${event.kind}]\x1B[0m ${specName} \x1B[90m${text}\x1B[0m`),ndjson)emitNdjson({type:"qa:event",specKey,domain,team,event:{timestamp:event.timestamp,kind:event.kind,agent:event.agent??"",text:event.text??""}})},{pollIntervalMs:250});console.error(`
4442
4445
  [qa] Running ${prepared.length} specs (max ${maxConcurrency} parallel)
4443
4446
  `);let reports=[],running2=0,nextIdx=0,startTime=Date.now();await new Promise((resolveAll)=>{let tryStartNext=()=>{while(running2<maxConcurrency&&nextIdx<prepared.length){let p=prepared[nextIdx++];running2++,emitQaEvent(repoPath,"spec-started",{type:"qa:spec-started",specKey:p.entry.key,domain:p.entry.domain,team:p.teamName},ndjson),runPreparedSpec(repoPath,p.spec,p.teamName,p.worktreePath,p.promptFile,timeoutMs).then(async(report2)=>{let key=specKeyFromPath(specDir,p.entry.filePath);await saveResult(repoPath,key,report2);let icon=report2.result==="pass"?`${"\x1B[32m"}\u2713${"\x1B[0m"}`:`${"\x1B[31m"}\u2717${"\x1B[0m"}`,elapsed=((Date.now()-startTime)/1000).toFixed(0);console.error(` ${icon} ${p.entry.name} (${(report2.durationMs/1000).toFixed(0)}s) [${elapsed}s total]`),await emitSpecDone(repoPath,p.entry.key,p.entry.domain,p.teamName,report2,ndjson),reports.push(report2)}).catch((err)=>{let errorReport=makeErrorReport(p.spec,Date.now(),String(err));reports.push(errorReport),console.error(` ${"\x1B[31m"}\u2717${"\x1B[0m"} ${p.entry.name}: ${err}`),emitSpecDone(repoPath,p.entry.key,p.entry.domain,p.teamName,errorReport,ndjson)}).finally(()=>{if(running2--,reports.length===prepared.length)resolveAll();else tryStartNext()})}};tryStartNext()}),await timelineSub.stop(),console.error(`
@@ -4591,9 +4594,9 @@ Team: ${teamName}
4591
4594
  LIMIT ${limit}
4592
4595
  `;if(rows.length===0){console.log(`No execution history for schedule "${schedule.name}"`),await shutdown();return}console.log(`
4593
4596
  History for "${schedule.name}":
4594
- `);let tableRows=rows.map((r)=>[formatTimestamp2(r.due_at),r.trigger_status,r.run_status??"-",formatDuration4(r.duration_ms),r.error?r.error.slice(0,60):"-"]);printTable3(["DUE AT","TRIGGER","RUN","DURATION","ERROR"],tableRows),await shutdown()}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function registerScheduleCommands(program2){let schedule=program2.command("schedule").description("Manage scheduled triggers");schedule.command("create <name>").description("Create a new schedule").requiredOption("--command <cmd>",'Command to execute (e.g., "genie spawn reviewer")').option("--at <time>","One-time schedule at absolute time (ISO 8601)").option("--every <interval>","Repeating schedule: duration (10m, 2h, 24h) or cron expression").option("--after <duration>","One-time schedule after delay (10m, 2h)").option("--timezone <tz>","Timezone for schedule (default: UTC)","UTC").option("--lease-timeout <duration>","Lease timeout for runs (default: 5m)").action(async(name,options)=>{await scheduleCreateCommand(name,options)}),schedule.command("list").description("List schedules with next due trigger").option("--json","Output as JSON").option("--watch","Refresh every 2s").action(async(options)=>{await scheduleListCommand(options)}),schedule.command("cancel <name>").description("Cancel a schedule and skip pending triggers").option("--filter <expr>","Filter expression (e.g., status=pending)").action(async(name,options)=>{await scheduleCancelCommand(name,options)}),schedule.command("retry <name>").description("Reset a failed trigger to pending").action(async(name)=>{await scheduleRetryCommand(name)}),schedule.command("history <name>").description("Show past executions for a schedule").option("--limit <n>","Max rows to show (default: 20)",Number.parseInt).action(async(name,options)=>{await scheduleHistoryCommand(name,options)})}import{spawnSync as spawnSync9}from"child_process";import{existsSync as existsSync72,readFileSync as readFileSync48,readdirSync as readdirSync16,realpathSync as realpathSync8}from"fs";import{dirname as dirname30,join as join87,resolve as resolve19}from"path";var defaultDeps5={existsSync:existsSync72,realpathSync:realpathSync8,readFileSync:(path3,encoding)=>readFileSync48(path3,encoding),spawnSync:(command,args,options)=>spawnSync9(command,args,options),setExitCode:(exitCode)=>{process.exitCode=exitCode},stdout:(line)=>process.stdout.write(`${line}
4597
+ `);let tableRows=rows.map((r)=>[formatTimestamp2(r.due_at),r.trigger_status,r.run_status??"-",formatDuration4(r.duration_ms),r.error?r.error.slice(0,60):"-"]);printTable3(["DUE AT","TRIGGER","RUN","DURATION","ERROR"],tableRows),await shutdown()}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function registerScheduleCommands(program2){let schedule=program2.command("schedule").description("Manage scheduled triggers");schedule.command("create <name>").description("Create a new schedule").requiredOption("--command <cmd>",'Command to execute (e.g., "genie spawn reviewer")').option("--at <time>","One-time schedule at absolute time (ISO 8601)").option("--every <interval>","Repeating schedule: duration (10m, 2h, 24h) or cron expression").option("--after <duration>","One-time schedule after delay (10m, 2h)").option("--timezone <tz>","Timezone for schedule (default: UTC)","UTC").option("--lease-timeout <duration>","Lease timeout for runs (default: 5m)").action(async(name,options)=>{await scheduleCreateCommand(name,options)}),schedule.command("list").description("List schedules with next due trigger").option("--json","Output as JSON").option("--watch","Refresh every 2s").action(async(options)=>{await scheduleListCommand(options)}),schedule.command("cancel <name>").description("Cancel a schedule and skip pending triggers").option("--filter <expr>","Filter expression (e.g., status=pending)").action(async(name,options)=>{await scheduleCancelCommand(name,options)}),schedule.command("retry <name>").description("Reset a failed trigger to pending").action(async(name)=>{await scheduleRetryCommand(name)}),schedule.command("history <name>").description("Show past executions for a schedule").option("--limit <n>","Max rows to show (default: 20)",Number.parseInt).action(async(name,options)=>{await scheduleHistoryCommand(name,options)})}import{spawnSync as spawnSync9}from"child_process";import{existsSync as existsSync72,readFileSync as readFileSync48,readdirSync as readdirSync16,realpathSync as realpathSync9}from"fs";import{dirname as dirname31,join as join87,resolve as resolve19}from"path";var defaultDeps5={existsSync:existsSync72,realpathSync:realpathSync9,readFileSync:(path3,encoding)=>readFileSync48(path3,encoding),spawnSync:(command,args,options)=>spawnSync9(command,args,options),setExitCode:(exitCode)=>{process.exitCode=exitCode},stdout:(line)=>process.stdout.write(`${line}
4595
4598
  `),stderr:(line)=>process.stderr.write(`${line}
4596
- `),now:()=>new Date};function collectRepeatedOption(value,previous){return[...previous,value]}function collectKillPid(value,previous){let pid=Number.parseInt(value,10);if(!Number.isFinite(pid)||pid<=0)throw Error(`--kill-pid expects a positive integer, got "${value}"`);return[...previous,pid]}function resolveGenieRoot2(argv1=process.argv[1],deps=defaultDeps5){try{if(argv1){let scriptDir=dirname30(deps.realpathSync(argv1)),candidates=[resolve19(scriptDir,".."),resolve19(scriptDir,"..","..")];for(let candidate of candidates)if(deps.existsSync(join87(candidate,"package.json")))return candidate}}catch{}return resolve19(import.meta.dir,"..","..")}function resolveSecScanScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join87(root,"scripts","sec-scan.cjs");if(!deps.existsSync(scriptPath))throw Error(`Security scanner payload not found at ${scriptPath}`);return scriptPath}function resolveSecRemediateScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join87(root,"scripts","sec-remediate.cjs");if(!deps.existsSync(scriptPath))throw Error(`Security remediation payload not found at ${scriptPath}`);return scriptPath}function resolveSecFixScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join87(root,"scripts","sec-fix.cjs");if(!deps.existsSync(scriptPath))throw Error(`Security fix payload not found at ${scriptPath}`);return scriptPath}function buildSecFixArgv(options){let args=[];if(options.yes)args.push("--yes");if(options.json)args.push("--json");if(options.skipReinstall)args.push("--skip-reinstall");if(options.skipRescan)args.push("--skip-rescan");if(options.dryRun)args.push("--dry-run");if(options.unsafeUnverified)args.push("--unsafe-unverified",options.unsafeUnverified);return args}function runSecFix(options,deps=defaultDeps5){let args=[resolveSecFixScript(process.argv[1],deps),...buildSecFixArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}var BOOLEAN_FLAG_MAP=[["json","--json"],["allHomes","--all-homes"],["noProgress","--no-progress"],["quiet","--quiet"],["verbose","--verbose"],["progressJson","--progress-json"],["redact","--redact"],["impactSurface","--impact-surface"]],REPEATED_FLAG_MAP=[["home","--home"],["root","--root"],["phaseBudget","--phase-budget"]],STRING_FLAG_MAP=[["progressInterval","--progress-interval"],["eventsFile","--events-file"]];function buildSecScanArgv(options){let args=[];for(let[key,flag]of BOOLEAN_FLAG_MAP)if(options[key])args.push(flag);for(let[key,flag]of REPEATED_FLAG_MAP){let values2=options[key]??[];for(let value of values2)args.push(flag,value)}for(let[key,flag]of STRING_FLAG_MAP){let value=options[key];if(value)args.push(flag,value)}if(options.persist===!1)args.push("--no-persist");return args}function buildSecRemediateArgv(options){let args=[];if(options.dryRun)args.push("--dry-run");if(options.apply)args.push("--apply");if(options.resume)args.push("--resume",options.resume);if(options.scanReport)args.push("--scan-report",options.scanReport);if(options.scanId)args.push("--scan-id",options.scanId);if(options.plan)args.push("--plan",options.plan);if(options.quarantineDir)args.push("--quarantine-dir",options.quarantineDir);if(options.unsafeUnverified)args.push("--unsafe-unverified",options.unsafeUnverified);if(options.remediatePartial)args.push("--remediate-partial");if(options.confirmIncompleteScan)args.push("--confirm-incomplete-scan",options.confirmIncompleteScan);for(let pid of options.killPid??[])args.push("--kill-pid",String(pid));if(options.autoConfirmFrom)args.push("--auto-confirm-from",options.autoConfirmFrom);if(options.json)args.push("--json");return args}function runSecScan(options,deps=defaultDeps5){let args=[resolveSecScanScript(process.argv[1],deps),...buildSecScanArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecRemediate(options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecRemediateArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecRestore(quarantineId,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),"--restore",quarantineId],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function buildSecRollbackArgv(scanId,options){let args=["--rollback",scanId];if(options.json)args.push("--json");return args}function buildSecQuarantineListArgv(options){let args=["--quarantine-list"];if(options.json)args.push("--json");return args}function buildSecQuarantineGcArgv(options){let args=["--quarantine-gc"];if(options.olderThan)args.push("--older-than",options.olderThan);if(options.confirmGc)args.push("--confirm-gc",options.confirmGc);if(options.json)args.push("--json");return args}function runSecRollback(scanId,options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecRollbackArgv(scanId,options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecQuarantineList(options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecQuarantineListArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecQuarantineGc(options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecQuarantineGcArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function applySecScanExitCode(exitCode,deps=defaultDeps5){if(exitCode!==0)deps.setExitCode(exitCode)}var VERIFY_EXIT={VERIFIED:0,SIGNATURE_INVALID:2,SIGNER_IDENTITY_MISMATCH:3,PROVENANCE_INVALID:4,NO_SIGNATURE_MATERIAL:5,MISSING_BINARY:127},SIGNER_IDENTITY_REGEXP="^https://github.com/automagik-dev/genie/.github/workflows/release.yml@",SIGNER_OIDC_ISSUER="https://token.actions.githubusercontent.com",PROVENANCE_SOURCE_URI="github.com/automagik-dev/genie",COSIGN_NO_KEY_SENTINEL="BEGIN COSIGN NO-PINNED-KEY SENTINEL";function discoverSignatureBundle(bundleDir,deps=defaultDeps5){if(!deps.existsSync(bundleDir))return null;let candidates=[];try{for(let entry2 of readdirSync16(bundleDir))if(entry2.endsWith(".tgz"))candidates.push(entry2)}catch{return null}for(let tarballName of candidates){let tarball=join87(bundleDir,tarballName),signature=`${tarball}.sig`,certificate=`${tarball}.cert`;if(!deps.existsSync(signature))continue;if(!deps.existsSync(certificate))continue;let provenancePath=join87(bundleDir,"provenance.intoto.jsonl"),provenance=deps.existsSync(provenancePath)?provenancePath:null;return{tarball,signature,certificate,provenance}}return null}function readsAsCosignSentinel(path3,deps=defaultDeps5){if(!deps.existsSync(path3))return!1;try{return deps.readFileSync(path3,"utf8").includes(COSIGN_NO_KEY_SENTINEL)}catch{return!1}}function ensureBinary(name,deps){let result2=deps.spawnSync(name,["--version"],{stdio:"pipe",encoding:"utf8"});if(result2.error)return{ok:!1,binary:name,reason:result2.error.message};if((result2.status??1)!==0)return{ok:!1,binary:name,reason:`${name} --version exited non-zero`};return{ok:!0,binary:name}}function buildVerifyResult(exitCode,ctx){return{exitCode,json:{verified:exitCode===VERIFY_EXIT.VERIFIED,exit_code:exitCode,signer_identity:SIGNER_IDENTITY_REGEXP,signer_oidc_issuer:SIGNER_OIDC_ISSUER,signature_source:ctx.bundle?.signature??null,provenance_source:ctx.bundle?.provenance??null,tarball_path:ctx.bundle?.tarball??null,verified_at:ctx.verifiedAt,pinned_key_fingerprint:null,signing_mode:"cosign-keyless",offline:ctx.offline,errors:ctx.errors}}}function classifyCosignFailure(stderr){let lower=stderr.toLowerCase();return lower.includes("certificate identity")||lower.includes("subject does not match")||lower.includes("oidc issuer")?VERIFY_EXIT.SIGNER_IDENTITY_MISMATCH:VERIFY_EXIT.SIGNATURE_INVALID}function runCosignStep(bundle,offline,errors3,deps){let cosignCheck=ensureBinary("cosign",deps);if(!cosignCheck.ok)return errors3.push(`cosign not available in PATH (${cosignCheck.reason??"unknown"}). Install from https://docs.sigstore.dev/cosign/installation/.`),VERIFY_EXIT.MISSING_BINARY;let cosignArgs=["verify-blob","--certificate-identity-regexp",SIGNER_IDENTITY_REGEXP,"--certificate-oidc-issuer",SIGNER_OIDC_ISSUER,"--signature",bundle.signature,"--certificate",bundle.certificate,bundle.tarball];if(offline)cosignArgs.push("--insecure-ignore-tlog","--offline");let result2=deps.spawnSync("cosign",cosignArgs,{stdio:"pipe",encoding:"utf8"});if(result2.error)return errors3.push(`cosign spawn failed: ${result2.error.message}`),VERIFY_EXIT.MISSING_BINARY;if((result2.status??1)===0)return VERIFY_EXIT.VERIFIED;let stderr=typeof result2.stderr==="string"?result2.stderr:"";if(stderr)errors3.push(stderr.trim());return classifyCosignFailure(stderr)}function runSlsaStep(bundle,errors3,deps){if(!bundle.provenance)return errors3.push(`provenance.intoto.jsonl missing alongside ${bundle.tarball} \u2014 cosign passed but SLSA provenance cannot be checked.`),VERIFY_EXIT.PROVENANCE_INVALID;let slsaCheck=ensureBinary("slsa-verifier",deps);if(!slsaCheck.ok)return errors3.push(`slsa-verifier not available in PATH (${slsaCheck.reason??"unknown"}). Install from https://github.com/slsa-framework/slsa-verifier.`),VERIFY_EXIT.MISSING_BINARY;let result2=deps.spawnSync("slsa-verifier",["verify-artifact",bundle.tarball,"--provenance-path",bundle.provenance,"--source-uri",PROVENANCE_SOURCE_URI],{stdio:"pipe",encoding:"utf8"});if(result2.error)return errors3.push(`slsa-verifier spawn failed: ${result2.error.message}`),VERIFY_EXIT.MISSING_BINARY;if((result2.status??1)===0)return VERIFY_EXIT.VERIFIED;let stderr=typeof result2.stderr==="string"?result2.stderr:"";if(stderr)errors3.push(stderr.trim());return VERIFY_EXIT.PROVENANCE_INVALID}function resolveBundleDir(options,genieRoot){if(options.bundleDir)return options.bundleDir;if(options.tarball)return dirname30(resolve19(options.tarball));return resolve19(genieRoot)}function runVerifyInstall(options,deps=defaultDeps5){let errors3=[],verifiedAt=deps.now().toISOString(),offline=options.offline===!0,genieRoot=resolveGenieRoot2(process.argv[1],deps),bundleDir=resolveBundleDir(options,genieRoot),bundle=discoverSignatureBundle(bundleDir,deps),ctx={bundle,verifiedAt,offline,errors:errors3};if(!bundle){if(errors3.push(`No signed release bundle found under ${bundleDir}. Expected <pkg>.tgz + .sig + .cert + provenance.intoto.jsonl.`),readsAsCosignSentinel(join87(genieRoot,".github","cosign.pub"),deps))errors3.push(".github/cosign.pub is the documented NO-KEY sentinel \u2014 release signing is cosign KEYLESS ONLY; there is no public key to pin.");return buildVerifyResult(VERIFY_EXIT.NO_SIGNATURE_MATERIAL,ctx)}let cosignExit=runCosignStep(bundle,offline,errors3,deps);if(cosignExit!==VERIFY_EXIT.VERIFIED)return buildVerifyResult(cosignExit,ctx);let slsaExit=runSlsaStep(bundle,errors3,deps);return buildVerifyResult(slsaExit,ctx)}function emitHumanReport(result2,options,deps){let{json:json2,exitCode}=result2,status2=json2.verified?"OK":"FAIL";if(deps.stdout(`verify-install: ${status2} (exit ${exitCode})`),deps.stdout(` signing mode: ${json2.signing_mode}`),deps.stdout(` signer identity: ${json2.signer_identity}`),deps.stdout(` OIDC issuer: ${json2.signer_oidc_issuer}`),deps.stdout(` provenance source: ${PROVENANCE_SOURCE_URI}`),deps.stdout(` tarball: ${json2.tarball_path??"(not found)"}`),deps.stdout(` signature: ${json2.signature_source??"(not found)"}`),deps.stdout(` provenance: ${json2.provenance_source??"(not found)"}`),deps.stdout(` verified_at: ${json2.verified_at}`),deps.stdout(` offline: ${json2.offline?"yes (skips Rekor tlog)":"no"}`),options.offline)deps.stdout(" warning: offline mode skips the Rekor transparency log; revoked certs are not detected.");if(json2.errors.length>0){deps.stderr("verify-install errors:");for(let err of json2.errors)deps.stderr(` - ${err}`)}}function runVerifyInstallCommand(options,deps=defaultDeps5){let result2=runVerifyInstall(options,deps);if(options.json)deps.stdout(JSON.stringify(result2.json));else emitHumanReport(result2,options,deps);return result2.exitCode}function registerSecCommands(program2,deps=defaultDeps5){let sec=program2.command("sec").description("Security tooling \u2014 host compromise triage and IOC hunts");sec.command("scan",{isDefault:!0}).description("Scan host for TeamPCP/CanisterWorm-style package compromise indicators (read-only)").option("--json","Emit machine-readable report on stdout (for archival, CI, or piping to jq)").option("--all-homes","Blast-radius flag \u2014 scan every /root, /home/*, /Users/*, and WSL Windows home found on the host. When to reach for this: incident-response on a multi-tenant box or CI runner where per-user material must all be assessed in one pass.").option("--home <path>","Add one extra home directory to scan. When to reach for this: the scanner did not auto-discover a non-standard home (e.g. /var/lib/service-user) but you know it holds at-risk material.",collectRepeatedOption,[]).option("--root <path>","Blast-radius flag \u2014 add an application root (repeatable) to scan for lockfiles, node_modules, and project evidence. When to reach for this: a multi-service host where each service lives under its own prefix (e.g. --root /srv/app --root /opt/worker).",collectRepeatedOption,[]).option("--no-progress","Suppress progress output on stderr").option("--quiet","Suppress progress and banners on stderr").option("--verbose","Emit extra diagnostics on stderr").option("--progress-json","Emit progress as NDJSON events to stderr").option("--progress-interval <ms>","Progress tick interval in milliseconds").option("--events-file <path>","Append structured NDJSON events to a 0600-mode file").option("--redact","Hash $HOME-prefixed paths; scrub AWS/GitHub/npm/JWT patterns").option("--no-persist","Do not persist the report to $GENIE_HOME/sec-scan/").option("--impact-surface","Scan for at-risk local material (secrets, wallets, browsers)").option("--phase-budget <name=ms>","Budget (ms) for a named phase (repeatable)",collectRepeatedOption,[]).addHelpText("after",`
4599
+ `),now:()=>new Date};function collectRepeatedOption(value,previous){return[...previous,value]}function collectKillPid(value,previous){let pid=Number.parseInt(value,10);if(!Number.isFinite(pid)||pid<=0)throw Error(`--kill-pid expects a positive integer, got "${value}"`);return[...previous,pid]}function resolveGenieRoot2(argv1=process.argv[1],deps=defaultDeps5){try{if(argv1){let scriptDir=dirname31(deps.realpathSync(argv1)),candidates=[resolve19(scriptDir,".."),resolve19(scriptDir,"..","..")];for(let candidate of candidates)if(deps.existsSync(join87(candidate,"package.json")))return candidate}}catch{}return resolve19(import.meta.dir,"..","..")}function resolveSecScanScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join87(root,"scripts","sec-scan.cjs");if(!deps.existsSync(scriptPath))throw Error(`Security scanner payload not found at ${scriptPath}`);return scriptPath}function resolveSecRemediateScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join87(root,"scripts","sec-remediate.cjs");if(!deps.existsSync(scriptPath))throw Error(`Security remediation payload not found at ${scriptPath}`);return scriptPath}function resolveSecFixScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join87(root,"scripts","sec-fix.cjs");if(!deps.existsSync(scriptPath))throw Error(`Security fix payload not found at ${scriptPath}`);return scriptPath}function buildSecFixArgv(options){let args=[];if(options.yes)args.push("--yes");if(options.json)args.push("--json");if(options.skipReinstall)args.push("--skip-reinstall");if(options.skipRescan)args.push("--skip-rescan");if(options.dryRun)args.push("--dry-run");if(options.unsafeUnverified)args.push("--unsafe-unverified",options.unsafeUnverified);return args}function runSecFix(options,deps=defaultDeps5){let args=[resolveSecFixScript(process.argv[1],deps),...buildSecFixArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}var BOOLEAN_FLAG_MAP=[["json","--json"],["allHomes","--all-homes"],["noProgress","--no-progress"],["quiet","--quiet"],["verbose","--verbose"],["progressJson","--progress-json"],["redact","--redact"],["impactSurface","--impact-surface"]],REPEATED_FLAG_MAP=[["home","--home"],["root","--root"],["phaseBudget","--phase-budget"]],STRING_FLAG_MAP=[["progressInterval","--progress-interval"],["eventsFile","--events-file"]];function buildSecScanArgv(options){let args=[];for(let[key,flag]of BOOLEAN_FLAG_MAP)if(options[key])args.push(flag);for(let[key,flag]of REPEATED_FLAG_MAP){let values2=options[key]??[];for(let value of values2)args.push(flag,value)}for(let[key,flag]of STRING_FLAG_MAP){let value=options[key];if(value)args.push(flag,value)}if(options.persist===!1)args.push("--no-persist");return args}function buildSecRemediateArgv(options){let args=[];if(options.dryRun)args.push("--dry-run");if(options.apply)args.push("--apply");if(options.resume)args.push("--resume",options.resume);if(options.scanReport)args.push("--scan-report",options.scanReport);if(options.scanId)args.push("--scan-id",options.scanId);if(options.plan)args.push("--plan",options.plan);if(options.quarantineDir)args.push("--quarantine-dir",options.quarantineDir);if(options.unsafeUnverified)args.push("--unsafe-unverified",options.unsafeUnverified);if(options.remediatePartial)args.push("--remediate-partial");if(options.confirmIncompleteScan)args.push("--confirm-incomplete-scan",options.confirmIncompleteScan);for(let pid of options.killPid??[])args.push("--kill-pid",String(pid));if(options.autoConfirmFrom)args.push("--auto-confirm-from",options.autoConfirmFrom);if(options.json)args.push("--json");return args}function runSecScan(options,deps=defaultDeps5){let args=[resolveSecScanScript(process.argv[1],deps),...buildSecScanArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecRemediate(options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecRemediateArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecRestore(quarantineId,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),"--restore",quarantineId],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function buildSecRollbackArgv(scanId,options){let args=["--rollback",scanId];if(options.json)args.push("--json");return args}function buildSecQuarantineListArgv(options){let args=["--quarantine-list"];if(options.json)args.push("--json");return args}function buildSecQuarantineGcArgv(options){let args=["--quarantine-gc"];if(options.olderThan)args.push("--older-than",options.olderThan);if(options.confirmGc)args.push("--confirm-gc",options.confirmGc);if(options.json)args.push("--json");return args}function runSecRollback(scanId,options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecRollbackArgv(scanId,options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecQuarantineList(options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecQuarantineListArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function runSecQuarantineGc(options,deps=defaultDeps5){let args=[resolveSecRemediateScript(process.argv[1],deps),...buildSecQuarantineGcArgv(options)],result2=deps.spawnSync(process.execPath,args,{stdio:"inherit"});if(result2.error)throw result2.error;return result2.status??1}function applySecScanExitCode(exitCode,deps=defaultDeps5){if(exitCode!==0)deps.setExitCode(exitCode)}var VERIFY_EXIT={VERIFIED:0,SIGNATURE_INVALID:2,SIGNER_IDENTITY_MISMATCH:3,PROVENANCE_INVALID:4,NO_SIGNATURE_MATERIAL:5,MISSING_BINARY:127},SIGNER_IDENTITY_REGEXP="^https://github.com/automagik-dev/genie/.github/workflows/release.yml@",SIGNER_OIDC_ISSUER="https://token.actions.githubusercontent.com",PROVENANCE_SOURCE_URI="github.com/automagik-dev/genie",COSIGN_NO_KEY_SENTINEL="BEGIN COSIGN NO-PINNED-KEY SENTINEL";function discoverSignatureBundle(bundleDir,deps=defaultDeps5){if(!deps.existsSync(bundleDir))return null;let candidates=[];try{for(let entry2 of readdirSync16(bundleDir))if(entry2.endsWith(".tgz"))candidates.push(entry2)}catch{return null}for(let tarballName of candidates){let tarball=join87(bundleDir,tarballName),signature=`${tarball}.sig`,certificate=`${tarball}.cert`;if(!deps.existsSync(signature))continue;if(!deps.existsSync(certificate))continue;let provenancePath=join87(bundleDir,"provenance.intoto.jsonl"),provenance=deps.existsSync(provenancePath)?provenancePath:null;return{tarball,signature,certificate,provenance}}return null}function readsAsCosignSentinel(path3,deps=defaultDeps5){if(!deps.existsSync(path3))return!1;try{return deps.readFileSync(path3,"utf8").includes(COSIGN_NO_KEY_SENTINEL)}catch{return!1}}function ensureBinary(name,deps){let result2=deps.spawnSync(name,["--version"],{stdio:"pipe",encoding:"utf8"});if(result2.error)return{ok:!1,binary:name,reason:result2.error.message};if((result2.status??1)!==0)return{ok:!1,binary:name,reason:`${name} --version exited non-zero`};return{ok:!0,binary:name}}function buildVerifyResult(exitCode,ctx){return{exitCode,json:{verified:exitCode===VERIFY_EXIT.VERIFIED,exit_code:exitCode,signer_identity:SIGNER_IDENTITY_REGEXP,signer_oidc_issuer:SIGNER_OIDC_ISSUER,signature_source:ctx.bundle?.signature??null,provenance_source:ctx.bundle?.provenance??null,tarball_path:ctx.bundle?.tarball??null,verified_at:ctx.verifiedAt,pinned_key_fingerprint:null,signing_mode:"cosign-keyless",offline:ctx.offline,errors:ctx.errors}}}function classifyCosignFailure(stderr){let lower=stderr.toLowerCase();return lower.includes("certificate identity")||lower.includes("subject does not match")||lower.includes("oidc issuer")?VERIFY_EXIT.SIGNER_IDENTITY_MISMATCH:VERIFY_EXIT.SIGNATURE_INVALID}function runCosignStep(bundle,offline,errors3,deps){let cosignCheck=ensureBinary("cosign",deps);if(!cosignCheck.ok)return errors3.push(`cosign not available in PATH (${cosignCheck.reason??"unknown"}). Install from https://docs.sigstore.dev/cosign/installation/.`),VERIFY_EXIT.MISSING_BINARY;let cosignArgs=["verify-blob","--certificate-identity-regexp",SIGNER_IDENTITY_REGEXP,"--certificate-oidc-issuer",SIGNER_OIDC_ISSUER,"--signature",bundle.signature,"--certificate",bundle.certificate,bundle.tarball];if(offline)cosignArgs.push("--insecure-ignore-tlog","--offline");let result2=deps.spawnSync("cosign",cosignArgs,{stdio:"pipe",encoding:"utf8"});if(result2.error)return errors3.push(`cosign spawn failed: ${result2.error.message}`),VERIFY_EXIT.MISSING_BINARY;if((result2.status??1)===0)return VERIFY_EXIT.VERIFIED;let stderr=typeof result2.stderr==="string"?result2.stderr:"";if(stderr)errors3.push(stderr.trim());return classifyCosignFailure(stderr)}function runSlsaStep(bundle,errors3,deps){if(!bundle.provenance)return errors3.push(`provenance.intoto.jsonl missing alongside ${bundle.tarball} \u2014 cosign passed but SLSA provenance cannot be checked.`),VERIFY_EXIT.PROVENANCE_INVALID;let slsaCheck=ensureBinary("slsa-verifier",deps);if(!slsaCheck.ok)return errors3.push(`slsa-verifier not available in PATH (${slsaCheck.reason??"unknown"}). Install from https://github.com/slsa-framework/slsa-verifier.`),VERIFY_EXIT.MISSING_BINARY;let result2=deps.spawnSync("slsa-verifier",["verify-artifact",bundle.tarball,"--provenance-path",bundle.provenance,"--source-uri",PROVENANCE_SOURCE_URI],{stdio:"pipe",encoding:"utf8"});if(result2.error)return errors3.push(`slsa-verifier spawn failed: ${result2.error.message}`),VERIFY_EXIT.MISSING_BINARY;if((result2.status??1)===0)return VERIFY_EXIT.VERIFIED;let stderr=typeof result2.stderr==="string"?result2.stderr:"";if(stderr)errors3.push(stderr.trim());return VERIFY_EXIT.PROVENANCE_INVALID}function resolveBundleDir(options,genieRoot){if(options.bundleDir)return options.bundleDir;if(options.tarball)return dirname31(resolve19(options.tarball));return resolve19(genieRoot)}function runVerifyInstall(options,deps=defaultDeps5){let errors3=[],verifiedAt=deps.now().toISOString(),offline=options.offline===!0,genieRoot=resolveGenieRoot2(process.argv[1],deps),bundleDir=resolveBundleDir(options,genieRoot),bundle=discoverSignatureBundle(bundleDir,deps),ctx={bundle,verifiedAt,offline,errors:errors3};if(!bundle){if(errors3.push(`No signed release bundle found under ${bundleDir}. Expected <pkg>.tgz + .sig + .cert + provenance.intoto.jsonl.`),readsAsCosignSentinel(join87(genieRoot,".github","cosign.pub"),deps))errors3.push(".github/cosign.pub is the documented NO-KEY sentinel \u2014 release signing is cosign KEYLESS ONLY; there is no public key to pin.");return buildVerifyResult(VERIFY_EXIT.NO_SIGNATURE_MATERIAL,ctx)}let cosignExit=runCosignStep(bundle,offline,errors3,deps);if(cosignExit!==VERIFY_EXIT.VERIFIED)return buildVerifyResult(cosignExit,ctx);let slsaExit=runSlsaStep(bundle,errors3,deps);return buildVerifyResult(slsaExit,ctx)}function emitHumanReport(result2,options,deps){let{json:json2,exitCode}=result2,status2=json2.verified?"OK":"FAIL";if(deps.stdout(`verify-install: ${status2} (exit ${exitCode})`),deps.stdout(` signing mode: ${json2.signing_mode}`),deps.stdout(` signer identity: ${json2.signer_identity}`),deps.stdout(` OIDC issuer: ${json2.signer_oidc_issuer}`),deps.stdout(` provenance source: ${PROVENANCE_SOURCE_URI}`),deps.stdout(` tarball: ${json2.tarball_path??"(not found)"}`),deps.stdout(` signature: ${json2.signature_source??"(not found)"}`),deps.stdout(` provenance: ${json2.provenance_source??"(not found)"}`),deps.stdout(` verified_at: ${json2.verified_at}`),deps.stdout(` offline: ${json2.offline?"yes (skips Rekor tlog)":"no"}`),options.offline)deps.stdout(" warning: offline mode skips the Rekor transparency log; revoked certs are not detected.");if(json2.errors.length>0){deps.stderr("verify-install errors:");for(let err of json2.errors)deps.stderr(` - ${err}`)}}function runVerifyInstallCommand(options,deps=defaultDeps5){let result2=runVerifyInstall(options,deps);if(options.json)deps.stdout(JSON.stringify(result2.json));else emitHumanReport(result2,options,deps);return result2.exitCode}function registerSecCommands(program2,deps=defaultDeps5){let sec=program2.command("sec").description("Security tooling \u2014 host compromise triage and IOC hunts");sec.command("scan",{isDefault:!0}).description("Scan host for TeamPCP/CanisterWorm-style package compromise indicators (read-only)").option("--json","Emit machine-readable report on stdout (for archival, CI, or piping to jq)").option("--all-homes","Blast-radius flag \u2014 scan every /root, /home/*, /Users/*, and WSL Windows home found on the host. When to reach for this: incident-response on a multi-tenant box or CI runner where per-user material must all be assessed in one pass.").option("--home <path>","Add one extra home directory to scan. When to reach for this: the scanner did not auto-discover a non-standard home (e.g. /var/lib/service-user) but you know it holds at-risk material.",collectRepeatedOption,[]).option("--root <path>","Blast-radius flag \u2014 add an application root (repeatable) to scan for lockfiles, node_modules, and project evidence. When to reach for this: a multi-service host where each service lives under its own prefix (e.g. --root /srv/app --root /opt/worker).",collectRepeatedOption,[]).option("--no-progress","Suppress progress output on stderr").option("--quiet","Suppress progress and banners on stderr").option("--verbose","Emit extra diagnostics on stderr").option("--progress-json","Emit progress as NDJSON events to stderr").option("--progress-interval <ms>","Progress tick interval in milliseconds").option("--events-file <path>","Append structured NDJSON events to a 0600-mode file").option("--redact","Hash $HOME-prefixed paths; scrub AWS/GitHub/npm/JWT patterns").option("--no-persist","Do not persist the report to $GENIE_HOME/sec-scan/").option("--impact-surface","Scan for at-risk local material (secrets, wallets, browsers)").option("--phase-budget <name=ms>","Budget (ms) for a named phase (repeatable)",collectRepeatedOption,[]).addHelpText("after",`
4597
4600
  Examples:
4598
4601
  # Quick triage of the current project and every home on the host.
4599
4602
  $ genie sec scan --all-homes --root "$PWD"
@@ -4884,7 +4887,7 @@ ${mode}Closed ${result2.closed} task${result2.closed===1?"":"s"} from ${result2.
4884
4887
  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 ok2=await deleteTemplate2(t.id);console.log(ok2?`Deleted template "${t.name}".`:"Delete failed.")})}init_term_format();var _taskService9;async function getTaskService9(){if(!_taskService9)_taskService9=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService9}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(`
4885
4888
  ${types4.length} type${types4.length===1?"":"s"}`)}function printTypePipeline(t){if(console.log(`
4886
4889
  Type: ${t.name} (${t.id})`),t.description)console.log(`Description: ${t.description}`);if(t.icon)console.log(`Icon: ${t.icon}`);console.log(`Built-in: ${t.isBuiltin?"yes":"no"}`),console.log("\u2500".repeat(60)),console.log(`
4887
- Stage Pipeline:`);let stages=t.stages;for(let i2=0;i2<stages.length;i2++){let s2=stages[i2],arrow=i2<stages.length-1?" \u2192":"",gate=s2.gate?` [gate: ${s2.gate}]`:"",action=s2.action?` (action: ${s2.action})`:"",auto=s2.auto_advance?" [auto]":"";console.log(` ${i2+1}. ${s2.label??s2.name}${gate}${action}${auto}${arrow}`)}console.log("")}async function handleTypeList(options){console.warn("Warning: `genie type` is deprecated. Use `genie board` instead.");let types4=await(await getTaskService9()).listTypes();if(options.json){console.log(JSON.stringify(types4,null,2));return}printTypeTable(types4)}async function handleTypeShow(id,options){console.warn("Warning: `genie type` is deprecated. Use `genie board` instead.");let t=await(await getTaskService9()).getType(id);if(!t)console.error(`Error: Type not found: ${id}`),process.exit(1);if(options.json){console.log(JSON.stringify(t,null,2));return}printTypePipeline(t)}async function handleTypeCreate(name,options){console.warn("Warning: `genie type` is deprecated. Use `genie board` instead.");let ts3=await getTaskService9(),stages;try{if(stages=JSON.parse(options.stages),!Array.isArray(stages))throw Error("Stages must be a JSON array")}catch(err){console.error(`Error: Invalid stages JSON. ${err instanceof Error?err.message:String(err)}`),process.exit(1)}for(let s2 of stages)if(typeof s2!=="object"||s2===null||!("name"in s2))console.error('Error: Each stage must have at least a "name" field.'),process.exit(1);let id=name.toLowerCase().replace(/\s+/g,"-"),t=await ts3.createType({id,name,description:options.description,icon:options.icon,stages});console.log(`Created type "${t.name}" (${t.id}) with ${stages.length} stages.`)}function registerTypeCommands(program2){let type2=program2.command("type").description("Task type management");type2.command("list").description("List all task types").option("--json","Output as JSON").action(async(options)=>{try{await handleTypeList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),type2.command("show <id>").description("Show task type detail with stage pipeline").option("--json","Output as JSON").action(async(id,options)=>{try{await handleTypeShow(id,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),type2.command("create <name>").description("Create a custom task type").requiredOption("--stages <json>","Stages JSON array").option("--description <text>","Type description").option("--icon <icon>","Type icon").action(async(name,options)=>{try{await handleTypeCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_wish_lint();init_wish_parser();init_state();import{existsSync as existsSync74}from"fs";import{mkdir as mkdir12,readFile as readFile17,readdir as readdir11,stat as stat11,writeFile as writeFile11}from"fs/promises";import{dirname as dirname31,join as join89}from"path";function resolveTemplatePath(cwd=process.cwd()){let dir=cwd;for(let i2=0;i2<10;i2++){let candidate=join89(dir,"templates","wish-template.md");if(existsSync74(candidate))return candidate;let parent=dirname31(dir);if(parent===dir)break;dir=parent}return null}var FALLBACK_TEMPLATE=`# Wish: <TODO: title>
4890
+ Stage Pipeline:`);let stages=t.stages;for(let i2=0;i2<stages.length;i2++){let s2=stages[i2],arrow=i2<stages.length-1?" \u2192":"",gate=s2.gate?` [gate: ${s2.gate}]`:"",action=s2.action?` (action: ${s2.action})`:"",auto=s2.auto_advance?" [auto]":"";console.log(` ${i2+1}. ${s2.label??s2.name}${gate}${action}${auto}${arrow}`)}console.log("")}async function handleTypeList(options){console.warn("Warning: `genie type` is deprecated. Use `genie board` instead.");let types4=await(await getTaskService9()).listTypes();if(options.json){console.log(JSON.stringify(types4,null,2));return}printTypeTable(types4)}async function handleTypeShow(id,options){console.warn("Warning: `genie type` is deprecated. Use `genie board` instead.");let t=await(await getTaskService9()).getType(id);if(!t)console.error(`Error: Type not found: ${id}`),process.exit(1);if(options.json){console.log(JSON.stringify(t,null,2));return}printTypePipeline(t)}async function handleTypeCreate(name,options){console.warn("Warning: `genie type` is deprecated. Use `genie board` instead.");let ts3=await getTaskService9(),stages;try{if(stages=JSON.parse(options.stages),!Array.isArray(stages))throw Error("Stages must be a JSON array")}catch(err){console.error(`Error: Invalid stages JSON. ${err instanceof Error?err.message:String(err)}`),process.exit(1)}for(let s2 of stages)if(typeof s2!=="object"||s2===null||!("name"in s2))console.error('Error: Each stage must have at least a "name" field.'),process.exit(1);let id=name.toLowerCase().replace(/\s+/g,"-"),t=await ts3.createType({id,name,description:options.description,icon:options.icon,stages});console.log(`Created type "${t.name}" (${t.id}) with ${stages.length} stages.`)}function registerTypeCommands(program2){let type2=program2.command("type").description("Task type management");type2.command("list").description("List all task types").option("--json","Output as JSON").action(async(options)=>{try{await handleTypeList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),type2.command("show <id>").description("Show task type detail with stage pipeline").option("--json","Output as JSON").action(async(id,options)=>{try{await handleTypeShow(id,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),type2.command("create <name>").description("Create a custom task type").requiredOption("--stages <json>","Stages JSON array").option("--description <text>","Type description").option("--icon <icon>","Type icon").action(async(name,options)=>{try{await handleTypeCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_wish_lint();init_wish_parser();init_state();import{existsSync as existsSync74}from"fs";import{mkdir as mkdir11,readFile as readFile17,readdir as readdir11,stat as stat11,writeFile as writeFile11}from"fs/promises";import{dirname as dirname32,join as join89}from"path";function resolveTemplatePath(cwd=process.cwd()){let dir=cwd;for(let i2=0;i2<10;i2++){let candidate=join89(dir,"templates","wish-template.md");if(existsSync74(candidate))return candidate;let parent=dirname32(dir);if(parent===dir)break;dir=parent}return null}var FALLBACK_TEMPLATE=`# Wish: <TODO: title>
4888
4891
 
4889
4892
  | Field | Value |
4890
4893
  |-------|-------|
@@ -4944,7 +4947,7 @@ Stage Pipeline:`);let stages=t.stages;for(let i2=0;i2<stages.length;i2++){let s2
4944
4947
  \`\`\`
4945
4948
 
4946
4949
  **depends-on:** none
4947
- `;function renderTemplate(raw,slug,date){return raw.replace(/\{\{slug\}\}/g,slug).replace(/\{\{date\}\}/g,date)}function today(){let d=new Date,yyyy=d.getUTCFullYear(),mm=String(d.getUTCMonth()+1).padStart(2,"0"),dd=String(d.getUTCDate()).padStart(2,"0");return`${yyyy}-${mm}-${dd}`}async function wishNewCommand(slug,options){if(!/^[a-z0-9][a-z0-9-]*$/.test(slug))console.error(`\u274C Invalid slug "${slug}" \u2014 use lowercase letters, digits, and hyphens`),process.exit(1);let wishDir=join89(process.cwd(),".genie","wishes",slug),wishPath=join89(wishDir,"WISH.md");if(existsSync74(wishPath)&&!options.force)console.error(`\u274C Wish already exists: ${wishPath}`),console.error(" Pass --force to overwrite"),process.exit(1);let templatePath=resolveTemplatePath(),raw=templatePath?await readFile17(templatePath,"utf-8"):FALLBACK_TEMPLATE;if(!templatePath)console.warn("\u26A0\uFE0F templates/wish-template.md not found \u2014 using inline fallback skeleton");let rendered=renderTemplate(raw,slug,today());await mkdir12(wishDir,{recursive:!0}),await writeFile11(wishPath,rendered,"utf-8"),console.log(`\uD83D\uDCDD Created wish scaffold: ${wishPath}`),console.log(` Template: ${templatePath??"<inline fallback>"}`),console.log(` Next: edit the wish, then run \`genie wish lint ${slug}\` before dispatching`)}function renderDiff(before,after){let beforeLines=before.split(`
4950
+ `;function renderTemplate(raw,slug,date){return raw.replace(/\{\{slug\}\}/g,slug).replace(/\{\{date\}\}/g,date)}function today(){let d=new Date,yyyy=d.getUTCFullYear(),mm=String(d.getUTCMonth()+1).padStart(2,"0"),dd=String(d.getUTCDate()).padStart(2,"0");return`${yyyy}-${mm}-${dd}`}async function wishNewCommand(slug,options){if(!/^[a-z0-9][a-z0-9-]*$/.test(slug))console.error(`\u274C Invalid slug "${slug}" \u2014 use lowercase letters, digits, and hyphens`),process.exit(1);let wishDir=join89(process.cwd(),".genie","wishes",slug),wishPath=join89(wishDir,"WISH.md");if(existsSync74(wishPath)&&!options.force)console.error(`\u274C Wish already exists: ${wishPath}`),console.error(" Pass --force to overwrite"),process.exit(1);let templatePath=resolveTemplatePath(),raw=templatePath?await readFile17(templatePath,"utf-8"):FALLBACK_TEMPLATE;if(!templatePath)console.warn("\u26A0\uFE0F templates/wish-template.md not found \u2014 using inline fallback skeleton");let rendered=renderTemplate(raw,slug,today());await mkdir11(wishDir,{recursive:!0}),await writeFile11(wishPath,rendered,"utf-8"),console.log(`\uD83D\uDCDD Created wish scaffold: ${wishPath}`),console.log(` Template: ${templatePath??"<inline fallback>"}`),console.log(` Next: edit the wish, then run \`genie wish lint ${slug}\` before dispatching`)}function renderDiff(before,after){let beforeLines=before.split(`
4948
4951
  `),afterLines=after.split(`
4949
4952
  `),len=Math.max(beforeLines.length,afterLines.length),out=[];for(let i2=0;i2<len;i2++){let b2=beforeLines[i2],a=afterLines[i2];if(b2===a)continue;if(b2!==void 0)out.push(`- ${b2}`);if(a!==void 0)out.push(`+ ${a}`)}return out.join(`
4950
4953
  `)}function parseWishOrError(markdown){try{return parseWish(markdown)}catch(err){if(err instanceof WishParseError)return err;throw err}}function reportWishFileMissing(slug,wishPath,jsonMode){if(jsonMode)console.log(JSON.stringify({error:`Wish file not found: ${wishPath}`,rule:"missing-title",wish:slug,file:wishPath}));else console.error(`\u274C Wish file not found: ${wishPath}`);process.exit(1)}function emitLintReport(report2,wishPath,jsonMode){if(jsonMode)console.log(JSON.stringify(report2));else console.log(formatLintReport(report2,{color:process.stdout.isTTY??!1,path:wishPath}))}function exitWithErrorCount(report2){let errors3=report2.violations.filter((v)=>v.severity==="error").length;process.exit(errors3>0?1:0)}function handleNoFixableViolations(report2,wishPath,jsonMode){if(jsonMode)console.log(JSON.stringify({...report2,fixedViolations:0}));else console.log(formatLintReport(report2,{color:process.stdout.isTTY??!1,path:wishPath})),console.log(`
@@ -4969,7 +4972,7 @@ File not modified (--dry-run).`);process.exit(report2.summary.total>0?1:0)}async
4969
4972
  `+` Notes: bumped core@1.260507.5 \u2014 desktop rebuild required.
4970
4973
  `+` EOF
4971
4974
  )"`),process.exit(2);await doneCommand(ref,report2)}),wish.command("reset <ref>").option("-y, --yes","Skip confirmation prompt (required in non-interactive mode)").description("Reset wish state. <slug>#<group> resets one in-progress group; bare <slug> wipes the wish and recreates from current WISH.md").action(async(ref,options)=>{await resetAction(ref,options)}),wish.command("list").description("Enumerate all wishes with status, group counts, and progress").action(async()=>{await wishListCommand()})}var _T_BOOT=Date.now();try{let{execSync:execSyncStartup}=__require("child_process");if(execSyncStartup("git config core.bare",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()==="true")execSyncStartup("git config core.bare false",{stdio:["pipe","pipe","pipe"]})}catch{}function parseNumericFlag2(flagName){return(value)=>{let n=Number(value);if(Number.isNaN(n))throw Error(`${flagName} must be a number, got: ${value}`);return n}}if(process.env.GENIE_PROFILE_DB)console.error(`[profile] imports=${Date.now()-_T_BOOT}ms`);var program2=new Command;program2.name("genie").description("Genie CLI - AI-assisted development").version(VERSION);program2.option("--no-interactive","Disable interactive prompts (exit 2 instead of prompting)");program2.option("--no-tui","Skip TUI bootstrap (or set GENIE_TUI_DISABLE=1)");program2.configureHelp({sortSubcommands:!0,showGlobalOptions:!0});program2.configureOutput({outputError:(str5,write)=>{let cmd=program2.commands.find((c)=>process.argv.slice(2,6).includes(c.name())),prefix=cmd?`genie ${cmd.name()}`:"genie";write(`\x1B[31mError (${prefix}): ${str5}\x1B[0m
4972
- `)}});async function startNamedSession(name){let{randomUUID:randomUUID15}=await import("crypto"),{buildTeamLeadCommand:buildTeamLeadCommand2}=await Promise.resolve().then(() => (init_team_lead_command(),exports_team_lead_command)),{getAgentsFilePath:getAgentsFilePath2}=await Promise.resolve().then(() => (init_session(),exports_session)),systemPromptFile=getAgentsFilePath2(),sessionId=randomUUID15(),cmd=buildTeamLeadCommand2(name,{systemPromptFile:systemPromptFile??void 0,sessionId});console.log(`Starting new session: ${name}`);let{spawnSync:spawnSync11}=await import("child_process"),result2=spawnSync11("sh",["-c",cmd],{stdio:"inherit"});if(result2.status)process.exit(result2.status)}program2.command("setup").description("Configure genie settings").option("--quick","Accept all defaults").option("--shortcuts","Only configure keyboard shortcuts").option("--codex","Only configure Codex integration").option("--terminal","Only configure terminal defaults").option("--session","Only configure session settings").option("--reset","Reset configuration to defaults").option("--show","Show current configuration").action(async(options)=>{await setupCommand(options)});program2.command("install").description("Register genie-serve under pm2 with hardened defaults (canonical-pgserve-pm2-supervision wave 2)").option("--skip-pgserve","Don't run `pgserve install` first (operators who manage pgserve themselves)").action(async(options)=>{await installCommand(options)});program2.command("doctor").description("Run diagnostic checks on genie installation").option("--fix","Auto-fix: kill zombie postgres, clean shared memory, restart daemon").option("--observability","Report partition health + GENIE_WIDE_EMIT flag state").option("--perf","Report rolling per-handler P50/P99 from hook_perf_baseline + flag P99 regressions and recent fallback-log entries").option("--fix-team-orphans","Archive stale Claude-team config dirs missing config.json (paired with invincible-genie wish migration 050)").option("--dry-run","Pair with --fix-team-orphans to preview archive moves without mutating").option("--json","Emit JSON instead of human output (pairs with --observability)").action(doctorCommand);program2.command("recover-orphans").description("Attach orphaned Claude session JSONLs to executor rows so resume works").option("--dir <agent-dir>","Restrict the scan to one agent cwd (real path, not the encoded form)").option("--list","Dry-run \u2014 list orphaned JSONLs grouped by agent dir; never mutates").option("--apply","Mutate: attach orphans to executors. Requires --newest or --uuid.").option("--newest","Pair with --apply to auto-attach the newest orphan per agent dir").option("--uuid <session-id>","Pair with --apply to attach exactly one Claude session UUID").action(async(options)=>{await recoverOrphansCommand(options)});program2.command("update").description("Update Genie CLI to the latest version").option("--next","Switch to dev builds (npm @next tag)").option("--stable","Switch to stable releases (npm @latest tag)").option("-y, --yes","Skip the TTY confirmation prompt (or set GENIE_UPDATE_YES=1)").option("--no-restart","Skip post-update maintenance AND the verify probe").option("--no-verify","Run maintenance but skip the post-restart verify probe").option("--skip-maintenance","Skip post-update maintenance (or set GENIE_UPDATE_SKIP_MAINTENANCE=1)").option("--skip-cleanup <names>","Comma-separated legacy-artifact cleanup names to skip").option("--no-sidecar-cleanup","Accepted for cross-CLI portability with omni (no-op for genie)").action(updateCommand);program2.command("migrate").description("Apply pending genie host-migrations (auto-runs on install)").option("--dry-run","List pending migrations without executing").option("--quiet","Suppress per-step OK lines (used by postinstall)").option("--status","Show applied / pending / failed table").action(async(opts)=>{await migrateCommand({dryRun:opts.dryRun,quiet:opts.quiet,status:opts.status})});program2.command("uninstall").description("Remove Genie CLI and clean up hooks").action(uninstallCommand);var shortcuts=program2.command("shortcuts").description("Manage tmux keyboard shortcuts");shortcuts.action(shortcutsShowCommand);shortcuts.command("show").description("Show available shortcuts and installation status").action(shortcutsShowCommand);shortcuts.command("install").description("Install shortcuts to config files (~/.tmux.conf, shell rc)").action(shortcutsInstallCommand);shortcuts.command("uninstall").description("Remove shortcuts from config files").action(shortcutsUninstallCommand);registerServeCommands(program2);registerAppCommand(program2);registerInitCommands(program2);registerTeamNamespace(program2);registerDirNamespace(program2);registerAgentCommands(program2);registerObserveCommands(program2);registerOmniNamespace(program2);registerSendInboxCommands(program2);registerStateCommands(program2);registerDispatchCommands(program2);registerDispatchGroupCommands(program2);registerWishCommands(program2);registerHookNamespace(program2);registerDbCommands(program2);registerScheduleCommands(program2);registerDaemonCommands(program2);registerTaskCommands(program2);registerTypeCommands(program2);registerBoardCommands(program2);registerTagCommands(program2);registerReleaseCommands(program2);registerSecCommands(program2);registerProjectCommands(program2);registerPruneCommands(program2);registerNotifyCommands(program2);registerEventsCommands(program2);registerSessionsCommands(program2);registerMetricsCommands(program2);registerExportCommands(program2);registerImportCommands(program2);registerTemplateCommands(program2);registerBrainCommands(program2);registerBriefCommands(program2);registerApprovalCommands(program2);program2.command("done [ref]").description("Close the current turn (inside an agent session) or mark a wish group done (team-lead, <slug>#<group>)").option("-r, --report <message>","Full session handoff \u2014 what shipped, what is verified, what is left, surprises, decisions. REQUIRED. As long as it needs to be (multi-line OK; pass via heredoc).").action(async(ref,options)=>{let{doneAction:doneAction2}=await Promise.resolve().then(() => (init_done(),exports_done));await doneAction2(ref,options)});program2.command("blocked").description("Close the current turn with outcome=blocked").requiredOption("--reason <message>","Why the turn is blocked").action(async(options)=>{let{blockedAction:blockedAction2}=await Promise.resolve().then(() => (init_blocked(),exports_blocked));await blockedAction2(options)});program2.command("failed").description("Close the current turn with outcome=failed").requiredOption("--reason <message>","Why the turn failed").action(async(options)=>{let{failedAction:failedAction2}=await Promise.resolve().then(() => (init_failed(),exports_failed));await failedAction2(options)});program2.command("pane-trap").description("Internal: write clean_exit_unverified outcome for a dying pane/shell. Invoked by the tmux pane-died hook and the inline shell EXIT trap.").option("--pane-id <id>","tmux pane id (%N) \u2014 resolved to executor via executors.tmux_pane_id").option("--executor-id <id>","explicit executor UUID (preferred when available)").option("--reason <reason>","trap source: pane_died or shell_exit","pane_died").action(async(options)=>{let{paneTrapAction:paneTrapAction2}=await Promise.resolve().then(() => (init_pane_trap2(),exports_pane_trap));await paneTrapAction2(options)});installWorkspaceCheck(program2);var auditTimers=new Map,auditSpans=new Map;program2.hook("preAction",(_thisCommand,actionCommand)=>{let name=actionCommand.name();auditTimers.set(name,Date.now()),Promise.resolve().then(() => (init_db(),exports_db)).then(({isConnected:isConnected2})=>{if(!isConnected2())return;recordAuditEvent("command",name,"command_start",getActor(),{args:actionCommand.args}).catch(()=>{})}).catch(()=>{}),(async()=>{try{let{isWideEmitEnabled:isWideEmitEnabled2}=await Promise.resolve().then(() => exports_observability_flag);if(!isWideEmitEnabled2())return;let{startSpan:startSpan2}=await Promise.resolve().then(() => (init_emit(),exports_emit)),{getAmbient:getAmbient2}=await Promise.resolve().then(() => (init_trace_context(),exports_trace_context)),handle=startSpan2("cli.command",{command:name,args:actionCommand.args??[],cwd:process.cwd()},{severity:"debug",source_subsystem:"cli",ctx:getAmbient2()??void 0,agent:getActor()});auditSpans.set(name,handle)}catch{}})()});program2.hook("postAction",async(_thisCommand,actionCommand)=>{let name=actionCommand.name(),startMs=auditTimers.get(name),durationMs=startMs?Date.now()-startMs:void 0;auditTimers.delete(name);try{let{isConnected:isConnected2}=await Promise.resolve().then(() => (init_db(),exports_db));if(!isConnected2())return;await recordAuditEvent("command",name,"command_success",getActor(),{args:actionCommand.args,duration_ms:durationMs})}catch{}let handle=auditSpans.get(name);auditSpans.delete(name);try{if(handle){let{isWideEmitEnabled:isWideEmitEnabled2}=await Promise.resolve().then(() => exports_observability_flag);if(isWideEmitEnabled2()){let{endSpan:endSpan2}=await Promise.resolve().then(() => (init_emit(),exports_emit));endSpan2(handle,{exit_code:0,duration_ms:durationMs??0},{severity:"debug",source_subsystem:"cli",agent:getActor()})}}}catch{}try{let{flushNow:flushNow2}=await Promise.resolve().then(() => (init_emit(),exports_emit));await flushNow2()}catch{}});program2.command("spawn <name>").description("Spawn a new agent by name (resolves from directory or built-ins)").option("--provider <provider>","Provider: claude or codex","claude").option("--team <team>","Team name").option("--model <model>","Model override (e.g., sonnet, opus)").option("--skill <skill>","Skill to load (optional)").option("--layout <layout>","Layout mode: mosaic (default) or vertical").option("--color <color>","Teammate pane border color").option("--plan-mode","Start teammate in plan mode").option("--permission-mode <mode>","Permission mode (e.g., acceptEdits)").option("--extra-args <args...>","Extra CLI args forwarded to provider").option("--cwd <path>","Working directory for the agent (overrides directory entry)").option("--session <session>","Tmux session name to spawn into").option("--role <role>","Override role name for registration (avoids duplicate guard)").option("--new-window","Create a new tmux window instead of splitting").option("--window <target>","Tmux window to split into (e.g., genie:3)").option("--no-auto-resume","Disable auto-resume on pane death").option("--no-auto-sync","Disable auto-registration from workspace agents directory").option("--stream","Stream SDK messages to stdout in real-time (claude-sdk provider)").option("--stream-format <format>","Streaming output format: text, json, ndjson (default: text)","text").option("--sdk-max-turns <n>","SDK: max conversation turns",parseNumericFlag2("--sdk-max-turns")).option("--sdk-max-budget <usd>","SDK: max budget in USD",parseNumericFlag2("--sdk-max-budget")).option("--sdk-stream","SDK: enable streaming output (shortcut for --stream)").option("--sdk-effort <level>","SDK: reasoning effort level (low, medium, high, max)").option("--sdk-resume <session-id>","SDK: resume a previous session by ID").option("--prompt <text>","Initial prompt to send as the first user message").addHelpText("after",`
4975
+ `)}});async function startNamedSession(name){let{randomUUID:randomUUID15}=await import("crypto"),{buildTeamLeadCommand:buildTeamLeadCommand2}=await Promise.resolve().then(() => (init_team_lead_command(),exports_team_lead_command)),{getAgentsFilePath:getAgentsFilePath2}=await Promise.resolve().then(() => (init_session(),exports_session)),systemPromptFile=getAgentsFilePath2(),sessionId=randomUUID15(),cmd=buildTeamLeadCommand2(name,{systemPromptFile:systemPromptFile??void 0,sessionId});console.log(`Starting new session: ${name}`);let{spawnSync:spawnSync11}=await import("child_process"),result2=spawnSync11("sh",["-c",cmd],{stdio:"inherit"});if(result2.status)process.exit(result2.status)}program2.command("setup").description("Configure genie settings").option("--quick","Accept all defaults").option("--shortcuts","Only configure keyboard shortcuts").option("--codex","Only configure Codex integration").option("--terminal","Only configure terminal defaults").option("--session","Only configure session settings").option("--reset","Reset configuration to defaults").option("--show","Show current configuration").action(async(options)=>{await setupCommand(options)});program2.command("install").description("Register genie-serve under pm2 with hardened defaults (canonical-pgserve-pm2-supervision wave 2)").option("--skip-pgserve","Don't run `pgserve install` first (operators who manage pgserve themselves)").action(async(options)=>{await installCommand(options)});program2.command("doctor").description("Run diagnostic checks on genie installation").option("--fix","Auto-fix: kill zombie postgres, clean shared memory, restart daemon").option("--observability","Report partition health + GENIE_WIDE_EMIT flag state").option("--perf","Report rolling per-handler P50/P99 from hook_perf_baseline + flag P99 regressions and recent fallback-log entries").option("--fix-team-orphans","Archive stale Claude-team config dirs missing config.json (paired with invincible-genie wish migration 050)").option("--dry-run","Pair with --fix-team-orphans to preview archive moves without mutating").option("--json","Emit JSON instead of human output (pairs with --observability)").action(doctorCommand);program2.command("recover-orphans").description("Attach orphaned Claude session JSONLs to executor rows so resume works").option("--dir <agent-dir>","Restrict the scan to one agent cwd (real path, not the encoded form)").option("--list","Dry-run \u2014 list orphaned JSONLs grouped by agent dir; never mutates").option("--apply","Mutate: attach orphans to executors. Requires --newest or --uuid.").option("--newest","Pair with --apply to auto-attach the newest orphan per agent dir").option("--uuid <session-id>","Pair with --apply to attach exactly one Claude session UUID").action(async(options)=>{await recoverOrphansCommand(options)});program2.command("update").description("Update Genie CLI to the latest version (GitHub Releases)").option("--next","Switch to next/dev channel (.well-known/next.json)").option("--stable","Switch to stable channel (.well-known/latest.json)").option("-y, --yes","Skip the TTY confirmation prompt (or set GENIE_UPDATE_YES=1)").option("--no-restart","Skip post-update maintenance AND the verify probe").option("--no-verify","Run maintenance but skip the post-restart verify probe").option("--skip-maintenance","Skip post-update maintenance (or set GENIE_UPDATE_SKIP_MAINTENANCE=1)").option("--skip-cleanup <names>","Comma-separated legacy-artifact cleanup names to skip").option("--no-sidecar-cleanup","Accepted for cross-CLI portability with omni (no-op for genie)").option("--rollback","Restore the most recent ~/.genie/bin/.previous binary backup").action(updateCommand);program2.command("migrate").description("Apply pending genie host-migrations (auto-runs on install)").option("--dry-run","List pending migrations without executing").option("--quiet","Suppress per-step OK lines (used by postinstall)").option("--status","Show applied / pending / failed table").action(async(opts)=>{await migrateCommand({dryRun:opts.dryRun,quiet:opts.quiet,status:opts.status})});program2.command("uninstall").description("Remove Genie CLI and clean up hooks").action(uninstallCommand);var shortcuts=program2.command("shortcuts").description("Manage tmux keyboard shortcuts");shortcuts.action(shortcutsShowCommand);shortcuts.command("show").description("Show available shortcuts and installation status").action(shortcutsShowCommand);shortcuts.command("install").description("Install shortcuts to config files (~/.tmux.conf, shell rc)").action(shortcutsInstallCommand);shortcuts.command("uninstall").description("Remove shortcuts from config files").action(shortcutsUninstallCommand);registerServeCommands(program2);registerAppCommand(program2);registerInitCommands(program2);registerTeamNamespace(program2);registerDirNamespace(program2);registerAgentCommands(program2);registerObserveCommands(program2);registerOmniNamespace(program2);registerSendInboxCommands(program2);registerStateCommands(program2);registerDispatchCommands(program2);registerDispatchGroupCommands(program2);registerWishCommands(program2);registerHookNamespace(program2);registerDbCommands(program2);registerScheduleCommands(program2);registerDaemonCommands(program2);registerTaskCommands(program2);registerTypeCommands(program2);registerBoardCommands(program2);registerTagCommands(program2);registerReleaseCommands(program2);registerSecCommands(program2);registerProjectCommands(program2);registerPruneCommands(program2);registerNotifyCommands(program2);registerEventsCommands(program2);registerSessionsCommands(program2);registerMetricsCommands(program2);registerExportCommands(program2);registerImportCommands(program2);registerTemplateCommands(program2);registerBrainCommands(program2);registerBriefCommands(program2);registerApprovalCommands(program2);program2.command("done [ref]").description("Close the current turn (inside an agent session) or mark a wish group done (team-lead, <slug>#<group>)").option("-r, --report <message>","Full session handoff \u2014 what shipped, what is verified, what is left, surprises, decisions. REQUIRED. As long as it needs to be (multi-line OK; pass via heredoc).").action(async(ref,options)=>{let{doneAction:doneAction2}=await Promise.resolve().then(() => (init_done(),exports_done));await doneAction2(ref,options)});program2.command("blocked").description("Close the current turn with outcome=blocked").requiredOption("--reason <message>","Why the turn is blocked").action(async(options)=>{let{blockedAction:blockedAction2}=await Promise.resolve().then(() => (init_blocked(),exports_blocked));await blockedAction2(options)});program2.command("failed").description("Close the current turn with outcome=failed").requiredOption("--reason <message>","Why the turn failed").action(async(options)=>{let{failedAction:failedAction2}=await Promise.resolve().then(() => (init_failed(),exports_failed));await failedAction2(options)});program2.command("pane-trap").description("Internal: write clean_exit_unverified outcome for a dying pane/shell. Invoked by the tmux pane-died hook and the inline shell EXIT trap.").option("--pane-id <id>","tmux pane id (%N) \u2014 resolved to executor via executors.tmux_pane_id").option("--executor-id <id>","explicit executor UUID (preferred when available)").option("--reason <reason>","trap source: pane_died or shell_exit","pane_died").action(async(options)=>{let{paneTrapAction:paneTrapAction2}=await Promise.resolve().then(() => (init_pane_trap2(),exports_pane_trap));await paneTrapAction2(options)});installWorkspaceCheck(program2);var auditTimers=new Map,auditSpans=new Map;program2.hook("preAction",(_thisCommand,actionCommand)=>{let name=actionCommand.name();auditTimers.set(name,Date.now()),Promise.resolve().then(() => (init_db(),exports_db)).then(({isConnected:isConnected2})=>{if(!isConnected2())return;recordAuditEvent("command",name,"command_start",getActor(),{args:actionCommand.args}).catch(()=>{})}).catch(()=>{}),(async()=>{try{let{isWideEmitEnabled:isWideEmitEnabled2}=await Promise.resolve().then(() => exports_observability_flag);if(!isWideEmitEnabled2())return;let{startSpan:startSpan2}=await Promise.resolve().then(() => (init_emit(),exports_emit)),{getAmbient:getAmbient2}=await Promise.resolve().then(() => (init_trace_context(),exports_trace_context)),handle=startSpan2("cli.command",{command:name,args:actionCommand.args??[],cwd:process.cwd()},{severity:"debug",source_subsystem:"cli",ctx:getAmbient2()??void 0,agent:getActor()});auditSpans.set(name,handle)}catch{}})()});program2.hook("postAction",async(_thisCommand,actionCommand)=>{let name=actionCommand.name(),startMs=auditTimers.get(name),durationMs=startMs?Date.now()-startMs:void 0;auditTimers.delete(name);try{let{isConnected:isConnected2}=await Promise.resolve().then(() => (init_db(),exports_db));if(!isConnected2())return;await recordAuditEvent("command",name,"command_success",getActor(),{args:actionCommand.args,duration_ms:durationMs})}catch{}let handle=auditSpans.get(name);auditSpans.delete(name);try{if(handle){let{isWideEmitEnabled:isWideEmitEnabled2}=await Promise.resolve().then(() => exports_observability_flag);if(isWideEmitEnabled2()){let{endSpan:endSpan2}=await Promise.resolve().then(() => (init_emit(),exports_emit));endSpan2(handle,{exit_code:0,duration_ms:durationMs??0},{severity:"debug",source_subsystem:"cli",agent:getActor()})}}}catch{}try{let{flushNow:flushNow2}=await Promise.resolve().then(() => (init_emit(),exports_emit));await flushNow2()}catch{}});program2.command("spawn <name>").description("Spawn a new agent by name (resolves from directory or built-ins)").option("--provider <provider>","Provider: claude or codex","claude").option("--team <team>","Team name").option("--model <model>","Model override (e.g., sonnet, opus)").option("--skill <skill>","Skill to load (optional)").option("--layout <layout>","Layout mode: mosaic (default) or vertical").option("--color <color>","Teammate pane border color").option("--plan-mode","Start teammate in plan mode").option("--permission-mode <mode>","Permission mode (e.g., acceptEdits)").option("--extra-args <args...>","Extra CLI args forwarded to provider").option("--cwd <path>","Working directory for the agent (overrides directory entry)").option("--session <session>","Tmux session name to spawn into").option("--role <role>","Override role name for registration (avoids duplicate guard)").option("--new-window","Create a new tmux window instead of splitting").option("--window <target>","Tmux window to split into (e.g., genie:3)").option("--no-auto-resume","Disable auto-resume on pane death").option("--no-auto-sync","Disable auto-registration from workspace agents directory").option("--stream","Stream SDK messages to stdout in real-time (claude-sdk provider)").option("--stream-format <format>","Streaming output format: text, json, ndjson (default: text)","text").option("--sdk-max-turns <n>","SDK: max conversation turns",parseNumericFlag2("--sdk-max-turns")).option("--sdk-max-budget <usd>","SDK: max budget in USD",parseNumericFlag2("--sdk-max-budget")).option("--sdk-stream","SDK: enable streaming output (shortcut for --stream)").option("--sdk-effort <level>","SDK: reasoning effort level (low, medium, high, max)").option("--sdk-resume <session-id>","SDK: resume a previous session by ID").option("--prompt <text>","Initial prompt to send as the first user message").addHelpText("after",`
4973
4976
  Examples:
4974
4977
  genie spawn engineer # Spawn built-in engineer role
4975
4978
  genie spawn researcher --model sonnet # Spawn with model override