@automagik/genie 4.260429.39 → 4.260430.2
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
|
@@ -675,16 +675,16 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
|
|
|
675
675
|
tell.location
|
|
676
676
|
from (select lo_tell64($1) as location) tell
|
|
677
677
|
) seek
|
|
678
|
-
`};return resolve3(lo),new Promise(async(r)=>finish=r);async function readable({highWaterMark=16384,start=0,end=1/0}={}){let max=end-start;return start&&await lo.seek(start),new Stream2.Readable({highWaterMark,async read(size){let l=size>max?size-max:size;max-=size;let[{data}]=await lo.read(l);if(this.push(data),data.length<size)this.push(null)}})}async function writable({highWaterMark=16384,start=0}={}){return start&&await lo.seek(start),new Stream2.Writable({highWaterMark,write(chunk,encoding,callback){lo.write(chunk).then(()=>callback(),callback)}})}}).catch(reject)})}var init_large=()=>{};var exports_src={};__export(exports_src,{default:()=>src_default});import os from"os";import fs from"fs";function Postgres(a,b2){let options=parseOptions(a,b2),subscribe=options.no_subscribe||Subscribe(Postgres,{...options}),ending=!1,queries=queue_default(),connecting=queue_default(),reserved=queue_default(),closed=queue_default(),ended=queue_default(),open3=queue_default(),busy=queue_default(),full=queue_default(),queues={connecting,reserved,closed,ended,open:open3,busy,full},connections=[...Array(options.max)].map(()=>connection_default(options,queues,{onopen,onend,onclose})),sql=Sql(handler);return Object.assign(sql,{get parameters(){return options.parameters},largeObject:largeObject.bind(null,sql),subscribe,CLOSE,END:CLOSE,PostgresError,options,reserve,listen,begin,close,end}),sql;function Sql(handler2){return handler2.debug=options.debug,Object.entries(options.types).reduce((acc,[name,type2])=>{return acc[name]=(x)=>new Parameter(x,type2.to),acc},typed),Object.assign(sql2,{types:typed,typed,unsafe,notify,array,json:json2,file}),sql2;function typed(value,type2){return new Parameter(value,type2)}function sql2(strings,...args){return strings&&Array.isArray(strings.raw)?new Query(strings,args,handler2,cancel):typeof strings==="string"&&!args.length?new Identifier(options.transform.column.to?options.transform.column.to(strings):strings):new Builder(strings,args)}function unsafe(string,args=[],options2={}){return arguments.length===2&&!Array.isArray(args)&&(options2=args,args=[]),new Query([string],args,handler2,cancel,{prepare:!1,...options2,simple:"simple"in options2?options2.simple:args.length===0})}function file(path2,args=[],options2={}){return arguments.length===2&&!Array.isArray(args)&&(options2=args,args=[]),new Query([],args,(query2)=>{fs.readFile(path2,"utf8",(err,string)=>{if(err)return query2.reject(err);query2.strings=[string],handler2(query2)})},cancel,{...options2,simple:"simple"in options2?options2.simple:args.length===0})}}async function listen(name,fn,onlisten){let listener={fn,onlisten},sql2=listen.sql||(listen.sql=Postgres({...options,max:1,idle_timeout:null,max_lifetime:null,fetch_types:!1,onclose(){Object.entries(listen.channels).forEach(([name2,{listeners}])=>{delete listen.channels[name2],Promise.all(listeners.map((l)=>listen(name2,l.fn,l.onlisten).catch(()=>{})))})},onnotify(c,x){c in listen.channels&&listen.channels[c].listeners.forEach((l)=>l.fn(x))}})),channels=listen.channels||(listen.channels={});if(name in channels){channels[name].listeners.push(listener);let result3=await channels[name].result;return listener.onlisten&&listener.onlisten(),{state:result3.state,unlisten}}channels[name]={result:sql2`listen ${sql2.unsafe('"'+name.replace(/"/g,'""')+'"')}`,listeners:[listener]};let result2=await channels[name].result;return listener.onlisten&&listener.onlisten(),{state:result2.state,unlisten};async function unlisten(){if(name in channels===!1)return;if(channels[name].listeners=channels[name].listeners.filter((x)=>x!==listener),channels[name].listeners.length)return;return delete channels[name],sql2`unlisten ${sql2.unsafe('"'+name.replace(/"/g,'""')+'"')}`}}async function notify(channel,payload){return await sql`select pg_notify(${channel}, ${""+payload})`}async function reserve(){let queue=queue_default(),c=open3.length?open3.shift():await new Promise((resolve3,reject)=>{let query={reserve:resolve3,reject};queries.push(query),closed.length&&connect(closed.shift(),query)});move(c,reserved),c.reserved=()=>queue.length?c.execute(queue.shift()):move(c,reserved),c.reserved.release=!0;let sql2=Sql(handler2);return sql2.release=()=>{c.reserved=null,onopen(c)},sql2;function handler2(q){c.queue===full?queue.push(q):c.execute(q)||move(c,full)}}async function begin(options2,fn){!fn&&(fn=options2,options2="");let queries2=queue_default(),savepoints=0,connection2,prepare=null;try{return await sql.unsafe("begin "+options2.replace(/[^a-z ]/ig,""),[],{onexecute}).execute(),await Promise.race([scope(connection2,fn),new Promise((_,reject)=>connection2.onclose=reject)])}catch(error){throw error}async function scope(c,fn2,name){let sql2=Sql(handler2);sql2.savepoint=savepoint,sql2.prepare=(x)=>prepare=x.replace(/[^a-z0-9$-_. ]/gi);let uncaughtError,result2;name&&await sql2`savepoint ${sql2(name)}`;try{if(result2=await new Promise((resolve3,reject)=>{let x=fn2(sql2);Promise.resolve(Array.isArray(x)?Promise.all(x):x).then(resolve3,reject)}),uncaughtError)throw uncaughtError}catch(e){throw await(name?sql2`rollback to ${sql2(name)}`:sql2`rollback`),e instanceof PostgresError&&e.code==="25P02"&&uncaughtError||e}if(!name)prepare?await sql2`prepare transaction '${sql2.unsafe(prepare)}'`:await sql2`commit`;return result2;function savepoint(name2,fn3){if(name2&&Array.isArray(name2.raw))return savepoint((sql3)=>sql3.apply(sql3,arguments));return arguments.length===1&&(fn3=name2,name2=null),scope(c,fn3,"s"+savepoints+++(name2?"_"+name2:""))}function handler2(q){q.catch((e)=>uncaughtError||(uncaughtError=e)),c.queue===full?queries2.push(q):c.execute(q)||move(c,full)}}function onexecute(c){connection2=c,move(c,reserved),c.reserved=()=>queries2.length?c.execute(queries2.shift()):move(c,reserved)}}function move(c,queue){return c.queue.remove(c),queue.push(c),c.queue=queue,queue===open3?c.idleTimer.start():c.idleTimer.cancel(),c}function json2(x){return new Parameter(x,3802)}function array(x,type2){if(!Array.isArray(x))return array(Array.from(arguments));return new Parameter(x,type2||(x.length?inferType(x)||25:0),options.shared.typeArrayMap)}function handler(query){if(ending)return query.reject(Errors.connection("CONNECTION_ENDED",options,options));if(open3.length)return go(open3.shift(),query);if(closed.length)return connect(closed.shift(),query);busy.length?go(busy.shift(),query):queries.push(query)}function go(c,query){return c.execute(query)?move(c,busy):move(c,full)}function cancel(query){return new Promise((resolve3,reject)=>{query.state?query.active?connection_default(options).cancel(query.state,resolve3,reject):query.cancelled={resolve:resolve3,reject}:(queries.remove(query),query.cancelled=!0,query.reject(Errors.generic("57014","canceling statement due to user request")),resolve3())})}async function end({timeout=null}={}){if(ending)return ending;await 1;let timer2;return ending=Promise.race([new Promise((r)=>timeout!==null&&(timer2=setTimeout(destroy,timeout*1000,r))),Promise.all(connections.map((c)=>c.end()).concat(listen.sql?listen.sql.end({timeout:0}):[],subscribe.sql?subscribe.sql.end({timeout:0}):[]))]).then(()=>clearTimeout(timer2))}async function close(){await Promise.all(connections.map((c)=>c.end()))}async function destroy(resolve3){await Promise.all(connections.map((c)=>c.terminate()));while(queries.length)queries.shift().reject(Errors.connection("CONNECTION_DESTROYED",options));resolve3()}function connect(c,query){return move(c,connecting),c.connect(query),c}function onend(c){move(c,ended)}function onopen(c){if(queries.length===0)return move(c,open3);let max=Math.ceil(queries.length/(connecting.length+1)),ready=!0;while(ready&&queries.length&&max-- >0){let query=queries.shift();if(query.reserve)return query.reserve(c);ready=c.execute(query)}ready?move(c,busy):move(c,full)}function onclose(c,e){move(c,closed),c.reserved=null,c.onclose&&(c.onclose(e),c.onclose=null),options.onclose&&options.onclose(c.id),queries.length&&connect(c,queries.shift())}}function parseOptions(a,b2){if(a&&a.shared)return a;let env=process.env,o=(!a||typeof a==="string"?b2:a)||{},{url,multihost}=parseUrl(a),query=[...url.searchParams].reduce((a2,[b3,c])=>(a2[b3]=c,a2),{}),host=o.hostname||o.host||multihost||url.hostname||env.PGHOST||"localhost",port=o.port||url.port||env.PGPORT||5432,user=o.user||o.username||url.username||env.PGUSERNAME||env.PGUSER||osUsername();o.no_prepare&&(o.prepare=!1),query.sslmode&&(query.ssl=query.sslmode,delete query.sslmode),"timeout"in o&&(console.log("The timeout option is deprecated, use idle_timeout instead"),o.idle_timeout=o.timeout),query.sslrootcert==="system"&&(query.ssl="verify-full");let ints=["idle_timeout","connect_timeout","max_lifetime","max_pipeline","backoff","keep_alive"],defaults={max:globalThis.Cloudflare?3:10,ssl:!1,sslnegotiation:null,idle_timeout:null,connect_timeout:30,max_lifetime,max_pipeline:100,backoff,keep_alive:60,prepare:!0,debug:!1,fetch_types:!0,publications:"alltables",target_session_attrs:null};return{host:Array.isArray(host)?host:host.split(",").map((x)=>x.split(":")[0]),port:Array.isArray(port)?port:host.split(",").map((x)=>parseInt(x.split(":")[1]||port)),path:o.path||host.indexOf("/")>-1&&host+"/.s.PGSQL."+port,database:o.database||o.db||(url.pathname||"").slice(1)||env.PGDATABASE||user,user,pass:o.pass||o.password||url.password||env.PGPASSWORD||"",...Object.entries(defaults).reduce((acc,[k,d])=>{let value=k in o?o[k]:(k in query)?query[k]==="disable"||query[k]==="false"?!1:query[k]:env["PG"+k.toUpperCase()]||d;return acc[k]=typeof value==="string"&&ints.includes(k)?+value:value,acc},{}),connection:{application_name:env.PGAPPNAME||"postgres.js",...o.connection,...Object.entries(query).reduce((acc,[k,v])=>((k in defaults)||(acc[k]=v),acc),{})},types:o.types||{},target_session_attrs:tsa(o,url,env),onnotice:o.onnotice,onnotify:o.onnotify,onclose:o.onclose,onparameter:o.onparameter,socket:o.socket,transform:parseTransform(o.transform||{undefined:void 0}),parameters:{},shared:{retries:0,typeArrayMap:{}},...mergeUserTypes(o.types)}}function tsa(o,url,env){let x=o.target_session_attrs||url.searchParams.get("target_session_attrs")||env.PGTARGETSESSIONATTRS;if(!x||["read-write","read-only","primary","standby","prefer-standby"].includes(x))return x;throw Error("target_session_attrs "+x+" is not supported")}function backoff(retries){return(0.5+Math.random()/2)*Math.min(3**retries/100,20)}function max_lifetime(){return 60*(30+Math.random()*30)}function parseTransform(x){return{undefined:x.undefined,column:{from:typeof x.column==="function"?x.column:x.column&&x.column.from,to:x.column&&x.column.to},value:{from:typeof x.value==="function"?x.value:x.value&&x.value.from,to:x.value&&x.value.to},row:{from:typeof x.row==="function"?x.row:x.row&&x.row.from,to:x.row&&x.row.to}}}function parseUrl(url){if(!url||typeof url!=="string")return{url:{searchParams:new Map}};let host=url;host=host.slice(host.indexOf("://")+3).split(/[?/]/)[0],host=decodeURIComponent(host.slice(host.indexOf("@")+1));let urlObj=new URL(url.replace(host,host.split(",")[0]));return{url:{username:decodeURIComponent(urlObj.username),password:decodeURIComponent(urlObj.password),host:urlObj.host,hostname:urlObj.hostname,port:urlObj.port,pathname:urlObj.pathname,searchParams:urlObj.searchParams},multihost:host.indexOf(",")>-1&&host}}function osUsername(){try{return os.userInfo().username}catch(_){return process.env.USERNAME||process.env.USER||process.env.LOGNAME}}var src_default;var init_src=__esm(()=>{init_types3();init_connection();init_query();init_queue();init_errors2();init_large();Object.assign(Postgres,{PostgresError,toPascal,pascal,toCamel,camel,toKebab,kebab,fromPascal,fromCamel,fromKebab,BigInt:{to:20,from:[20],parse:(x)=>BigInt(x),serialize:(x)=>x.toString()}});src_default=Postgres});var exports_db={};__export(exports_db,{shutdown:()=>shutdown,runRetention:()=>runRetention,resolveTcpPgPassword:()=>resolveTcpPgPassword,resolvePgserveSocketDir:()=>resolvePgserveSocketDir,resolvePgserveLibpqSocketPath:()=>resolvePgserveLibpqSocketPath,resolvePgserveDaemonPidPath:()=>resolvePgserveDaemonPidPath,resolvePgserveControlSocketPath:()=>resolvePgserveControlSocketPath,resolvePgserveAuthPassword:()=>resolvePgserveAuthPassword,resolveDatabaseName:()=>resolveDatabaseName,resetConnection:()=>resetConnection,probePgserveDaemon:()=>probePgserveDaemon,isSocketMode:()=>isSocketMode,isConnected:()=>isConnected,isAvailable:()=>isAvailable,getOrStartDaemon:()=>getOrStartDaemon,getLockfilePath:()=>getLockfilePath,getDataDir:()=>getDataDir,getConnection:()=>getConnection,getActivePort:()=>getActivePort,ensurePgserve:()=>ensurePgserve,checkRootGuard:()=>checkRootGuard,autoStartDaemon:()=>autoStartDaemon,__setSpawnDaemonForTest:()=>__setSpawnDaemonForTest,DB_NAME:()=>DB_NAME});import{execSync as execSync3,spawn}from"child_process";import{existsSync as existsSync13,mkdirSync as mkdirSync6,readFileSync as readFileSync9,renameSync,unlinkSync as unlinkSync3,writeFileSync as writeFileSync6}from"fs";import{createConnection}from"net";import{homedir as homedir11}from"os";import{join as join17}from"path";import{pathToFileURL}from"url";function resolvePgserveSocketDir(){let xdg=process.env.XDG_RUNTIME_DIR,base=xdg&&xdg.length>0?xdg:"/tmp";return join17(base,"pgserve")}function resolveDatabaseName(){let testDbName=process.env.GENIE_TEST_DB_NAME;if(testDbName&&testDbName.length>0)return testDbName;return DB_NAME}function resolvePgserveAuthPassword(){let password=process.env.PGPASSWORD;return password&&password.length>0?password:DB_NAME}function resolvePgserveTimeoutMs(){let parsed=Number(process.env.GENIE_PGSERVE_TIMEOUT);return Number.isFinite(parsed)&&parsed>0?parsed:16000}function resolvePgConnectTimeoutSeconds(useSocket){let parsed=Number(process.env.GENIE_PG_CONNECT_TIMEOUT);if(Number.isFinite(parsed)&&parsed>0)return Math.ceil(parsed);if(!useSocket)return 5;return Math.max(16,Math.ceil(resolvePgserveTimeoutMs()/1000))}function resolveTcpPgPassword(){return resolvePgserveAuthPassword()}function resolvePgserveLibpqSocketPath(){return join17(resolvePgserveSocketDir(),".s.PGSQL.5432")}function resolvePgserveControlSocketPath(){return join17(resolvePgserveSocketDir(),"control.sock")}function resolvePgserveDaemonPidPath(){return join17(resolvePgserveSocketDir(),"pgserve.pid")}function probePgserveDaemon(){let socketPresent=existsSync13(resolvePgserveLibpqSocketPath()),pid=liveDaemonPid(readDaemonPid(resolvePgserveDaemonPidPath()));if(socketPresent&&pid!==null)return{running:!0,pid,socketPresent:!0};if(!socketPresent&&pid===null)return{running:!1,pid:null,socketPresent:!1,reason:"no daemon"};return{running:!1,pid,socketPresent,reason:socketPresent?"socket present but pid stale":"pid alive but no socket"}}function readDaemonPid(pidPath){if(!existsSync13(pidPath))return null;try{let raw=readFileSync9(pidPath,"utf-8").trim(),parsed=Number.parseInt(raw,10);return Number.isInteger(parsed)&&parsed>0?parsed:null}catch{return null}}function liveDaemonPid(pid){if(pid===null)return null;try{return process.kill(pid,0),pid}catch(err){return err.code==="EPERM"?pid:null}}function findLocalPgserveRoot(){let candidates=[join17(import.meta.dir,"..","node_modules","pgserve"),join17(import.meta.dir,"..","..","node_modules","pgserve")];for(let root of candidates)if(existsSync13(join17(root,"package.json")))return root;return null}function resolveLocalPgserveEntry(){let root=findLocalPgserveRoot();if(root===null)return null;try{let pkg=JSON.parse(readFileSync9(join17(root,"package.json"),"utf-8"));return join17(root,pkg.main??"src/index.js")}catch{return join17(root,"src/index.js")}}async function importPgserveSdk(){let localEntry=resolveLocalPgserveEntry();if(localEntry!==null&&existsSync13(localEntry))try{return await import(pathToFileURL(localEntry).href)}catch{}try{return await import("pgserve")}catch{return null}}function findPgserveDaemonBin(){let localRoot=findLocalPgserveRoot();if(localRoot!==null){let localBin=join17(localRoot,"bin","pgserve-wrapper.cjs");if(existsSync13(localBin))return localBin}try{let resolved=__require.resolve("pgserve/bin/pgserve-wrapper.cjs");if(existsSync13(resolved))return resolved}catch{}let globalBin=join17(homedir11(),".bun","bin","pgserve");if(existsSync13(globalBin))return globalBin;try{let fromPath=execSync3("which pgserve",{encoding:"utf-8",timeout:3000}).trim();if(fromPath.length>0)return fromPath}catch{}return null}function sleep(ms){return new Promise((r)=>setTimeout(r,ms))}async function getOrStartDaemon(){if(process.env.GENIE_PG_DISABLE_AUTOSTART==="1"||isPgAutostartDisabled()){let state=probePgserveDaemon();if(state.running)return state;throw Error("pgserve daemon unavailable and PG autostart is disabled")}let initial=probePgserveDaemon();if(initial.running)return initial;if(process.env.CI==="true"&&process.env.GENIE_PG_ALLOW_CI_AUTOSTART!=="1")throw Error("pgserve v2 daemon socket not present and CI=true. Either start `pgserve daemon` in the workflow or set GENIE_PG_ALLOW_CI_AUTOSTART=1 to opt in.");let rootErr=checkRootGuard();if(rootErr!==null)throw Error(rootErr);if(initial.reason==="socket present but pid stale"&&await isPgserveSocketAccepting())return{running:!0,pid:null,socketPresent:!0,reason:"socket accepts connections but pid file is stale"};if(daemonStartPromise)return await daemonStartPromise,probePgserveDaemon();daemonStartPromise=startPgserveDaemonOnce(initial);try{await daemonStartPromise}finally{daemonStartPromise=null}return probePgserveDaemon()}function cleanPartialDaemonState(initial){if(initial.reason==="pid alive but no socket"&&initial.pid!==null)unlinkIfPresent(resolvePgserveDaemonPidPath());if(initial.reason==="socket present but pid stale")removeStalePgserveSocketArtifacts()}async function isPgserveSocketAccepting(){let candidates=[resolvePgserveLibpqSocketPath(),resolvePgserveControlSocketPath()].filter((path2)=>existsSync13(path2));for(let path2 of candidates)if(await canConnectUnixSocket(path2))return!0;return!1}function canConnectUnixSocket(path2){return new Promise((resolve3)=>{let settled=!1,timer2=null,socket=null,finish=(ok)=>{if(settled)return;if(settled=!0,timer2)clearTimeout(timer2);socket?.removeAllListeners(),socket?.destroy(),resolve3(ok)};socket=createConnection(path2),timer2=setTimeout(()=>finish(!1),250),timer2.unref(),socket.once("connect",()=>finish(!0)),socket.once("error",()=>finish(!1))})}function removeStalePgserveSocketArtifacts(){for(let path2 of[resolvePgserveDaemonPidPath(),resolvePgserveLibpqSocketPath(),resolvePgserveControlSocketPath()])unlinkIfPresent(path2)}function unlinkIfPresent(path2){try{unlinkSync3(path2)}catch{}}async function startPgserveDaemonOnce(initial){if(cleanPartialDaemonState(initial),await tryEnsureDaemonWithSdk())return;let bin=requirePgserveDaemonBin();mkdirSync6(resolvePgserveSocketDir(),{recursive:!0,mode:448}),spawn(bin,["daemon","--data",DATA_DIR,"--log","warn"],{detached:!0,stdio:"ignore",env:{...process.env}}).unref(),await waitForDaemonSocket(bin)}function requirePgserveDaemonBin(){let bin=findPgserveDaemonBin();if(bin!==null)return bin;throw Error("pgserve binary not found. Install with `bun add pgserve@^2.0.2` (or `npm i pgserve@^2.0.2`), or start `pgserve daemon` manually before running genie.")}async function waitForDaemonSocket(bin){let socketPath=resolvePgserveLibpqSocketPath(),timeout=resolvePgserveTimeoutMs(),deadline=Date.now()+timeout;while(Date.now()<deadline){if(existsSync13(socketPath))return;await sleep(250)}throw Error(`pgserve v2 daemon did not bind ${socketPath} within ${Math.round(timeout/1000)}s. Try starting it manually: ${bin} daemon`)}async function tryEnsureDaemonWithSdk(){let sdk=await importPgserveSdk();if(sdk===null)return!1;if(typeof sdk.ensureDaemon!=="function")return!1;try{let state=await sdk.ensureDaemon({dataDir:DATA_DIR,logLevel:"warn",timeoutMs:resolvePgserveTimeoutMs(),controlSocketDir:resolvePgserveSocketDir()});return Boolean(state.running&&(state.libpqSocketPresent??state.socketPresent??!0))}catch{return cleanPartialDaemonState(probePgserveDaemon()),!1}}function maskCredentials(url){return url.replace(/\/\/.*@/,"//***@")}function checkRootGuard(){if(process.getuid?.()!==0)return null;if(process.env.GENIE_ALLOW_ROOT==="1")return null;return"pgserve cannot start under uid 0 (root) \u2014 PostgreSQL refuses to run as root for security reasons. "+"Run genie as a non-root user, or set GENIE_ALLOW_ROOT=1 to attempt anyway. See: https://github.com/automagik-dev/genie/issues/1226"}function isPgAutostartDisabled(){let value=process.env.GENIE_PG_NO_AUTOSTART;return value!==void 0&&TRUTHY_ENV.has(value.trim().toLowerCase())}function selfHealPostgres(dataDir){try{execSync3(`pkill -9 -f "postgres.*${dataDir.replace(/\//g,"\\/")}" 2>/dev/null || true`,{stdio:"ignore",timeout:5000}),execSync3(`pkill -9 -f "pgserve.*${dataDir.replace(/\//g,"\\/")}" 2>/dev/null || true`,{stdio:"ignore",timeout:5000})}catch{}let pidFile=join17(dataDir,"postmaster.pid");if(existsSync13(pidFile))try{unlinkSync3(pidFile)}catch{}try{execSync3("ipcs -m 2>/dev/null | awk '$6 == 0 {print $2}' | xargs -I{} ipcrm -m {} 2>/dev/null || true",{stdio:"ignore",timeout:5000})}catch{}}function signalPgserveTree(child,signal){let pid=child.pid;if(pid===void 0){try{child.kill(signal)}catch{}return}try{if(process.platform==="win32")child.kill(signal);else process.kill(-pid,signal)}catch{try{child.kill(signal)}catch{}}}async function terminatePgserveTree(child){if(signalPgserveTree(child,"SIGTERM"),!await new Promise((resolve3)=>{if(child.exitCode!==null||child.signalCode!==null){resolve3(!0);return}let timer2=setTimeout(()=>resolve3(!1),1000);timer2.unref(),child.once("exit",()=>{clearTimeout(timer2),resolve3(!0)})}))signalPgserveTree(child,"SIGKILL")}function getPort(){let envPort=process.env.GENIE_PG_PORT;if(envPort){let parsed=Number.parseInt(envPort,10);if(!Number.isNaN(parsed)&&parsed>0&&parsed<65536)return parsed}return DEFAULT_PORT}async function isPostgresHealthy(port){try{return await Promise.race([(async()=>{let pg=(await Promise.resolve().then(() => (init_src(),exports_src))).default,probe=pg({host:DEFAULT_HOST,port,database:DB_NAME,username:DB_NAME,password:resolveTcpPgPassword(),max:1,connect_timeout:3,idle_timeout:1});try{return await probe`SELECT 1`,await probe.end({timeout:2}),!0}catch{try{await probe.end({timeout:1})}catch{}return!1}})(),new Promise((resolve3)=>{setTimeout(()=>resolve3(!1),4000).unref()})])}catch{return!1}}function readLockfile(){try{let content=readFileSync9(LOCKFILE_PATH,"utf-8").trim(),port=Number.parseInt(content,10);if(!Number.isNaN(port)&&port>0&&port<65536)return port}catch{}return null}function writeLockfile(port){try{mkdirSync6(GENIE_HOME,{recursive:!0});let tmpPath=`${LOCKFILE_PATH}.tmp.${process.pid}`;writeFileSync6(tmpPath,String(port),"utf-8"),renameSync(tmpPath,LOCKFILE_PATH)}catch{}}function removeLockfile(){try{unlinkSync3(LOCKFILE_PATH)}catch{}}async function runRetention(sql){if(retentionRan)return;try{await sql.unsafe(`
|
|
678
|
+
`};return resolve3(lo),new Promise(async(r)=>finish=r);async function readable({highWaterMark=16384,start=0,end=1/0}={}){let max=end-start;return start&&await lo.seek(start),new Stream2.Readable({highWaterMark,async read(size){let l=size>max?size-max:size;max-=size;let[{data}]=await lo.read(l);if(this.push(data),data.length<size)this.push(null)}})}async function writable({highWaterMark=16384,start=0}={}){return start&&await lo.seek(start),new Stream2.Writable({highWaterMark,write(chunk,encoding,callback){lo.write(chunk).then(()=>callback(),callback)}})}}).catch(reject)})}var init_large=()=>{};var exports_src={};__export(exports_src,{default:()=>src_default});import os from"os";import fs from"fs";function Postgres(a,b2){let options=parseOptions(a,b2),subscribe=options.no_subscribe||Subscribe(Postgres,{...options}),ending=!1,queries=queue_default(),connecting=queue_default(),reserved=queue_default(),closed=queue_default(),ended=queue_default(),open3=queue_default(),busy=queue_default(),full=queue_default(),queues={connecting,reserved,closed,ended,open:open3,busy,full},connections=[...Array(options.max)].map(()=>connection_default(options,queues,{onopen,onend,onclose})),sql=Sql(handler);return Object.assign(sql,{get parameters(){return options.parameters},largeObject:largeObject.bind(null,sql),subscribe,CLOSE,END:CLOSE,PostgresError,options,reserve,listen,begin,close,end}),sql;function Sql(handler2){return handler2.debug=options.debug,Object.entries(options.types).reduce((acc,[name,type2])=>{return acc[name]=(x)=>new Parameter(x,type2.to),acc},typed),Object.assign(sql2,{types:typed,typed,unsafe,notify,array,json:json2,file}),sql2;function typed(value,type2){return new Parameter(value,type2)}function sql2(strings,...args){return strings&&Array.isArray(strings.raw)?new Query(strings,args,handler2,cancel):typeof strings==="string"&&!args.length?new Identifier(options.transform.column.to?options.transform.column.to(strings):strings):new Builder(strings,args)}function unsafe(string,args=[],options2={}){return arguments.length===2&&!Array.isArray(args)&&(options2=args,args=[]),new Query([string],args,handler2,cancel,{prepare:!1,...options2,simple:"simple"in options2?options2.simple:args.length===0})}function file(path2,args=[],options2={}){return arguments.length===2&&!Array.isArray(args)&&(options2=args,args=[]),new Query([],args,(query2)=>{fs.readFile(path2,"utf8",(err,string)=>{if(err)return query2.reject(err);query2.strings=[string],handler2(query2)})},cancel,{...options2,simple:"simple"in options2?options2.simple:args.length===0})}}async function listen(name,fn,onlisten){let listener={fn,onlisten},sql2=listen.sql||(listen.sql=Postgres({...options,max:1,idle_timeout:null,max_lifetime:null,fetch_types:!1,onclose(){Object.entries(listen.channels).forEach(([name2,{listeners}])=>{delete listen.channels[name2],Promise.all(listeners.map((l)=>listen(name2,l.fn,l.onlisten).catch(()=>{})))})},onnotify(c,x){c in listen.channels&&listen.channels[c].listeners.forEach((l)=>l.fn(x))}})),channels=listen.channels||(listen.channels={});if(name in channels){channels[name].listeners.push(listener);let result3=await channels[name].result;return listener.onlisten&&listener.onlisten(),{state:result3.state,unlisten}}channels[name]={result:sql2`listen ${sql2.unsafe('"'+name.replace(/"/g,'""')+'"')}`,listeners:[listener]};let result2=await channels[name].result;return listener.onlisten&&listener.onlisten(),{state:result2.state,unlisten};async function unlisten(){if(name in channels===!1)return;if(channels[name].listeners=channels[name].listeners.filter((x)=>x!==listener),channels[name].listeners.length)return;return delete channels[name],sql2`unlisten ${sql2.unsafe('"'+name.replace(/"/g,'""')+'"')}`}}async function notify(channel,payload){return await sql`select pg_notify(${channel}, ${""+payload})`}async function reserve(){let queue=queue_default(),c=open3.length?open3.shift():await new Promise((resolve3,reject)=>{let query={reserve:resolve3,reject};queries.push(query),closed.length&&connect(closed.shift(),query)});move(c,reserved),c.reserved=()=>queue.length?c.execute(queue.shift()):move(c,reserved),c.reserved.release=!0;let sql2=Sql(handler2);return sql2.release=()=>{c.reserved=null,onopen(c)},sql2;function handler2(q){c.queue===full?queue.push(q):c.execute(q)||move(c,full)}}async function begin(options2,fn){!fn&&(fn=options2,options2="");let queries2=queue_default(),savepoints=0,connection2,prepare=null;try{return await sql.unsafe("begin "+options2.replace(/[^a-z ]/ig,""),[],{onexecute}).execute(),await Promise.race([scope(connection2,fn),new Promise((_,reject)=>connection2.onclose=reject)])}catch(error){throw error}async function scope(c,fn2,name){let sql2=Sql(handler2);sql2.savepoint=savepoint,sql2.prepare=(x)=>prepare=x.replace(/[^a-z0-9$-_. ]/gi);let uncaughtError,result2;name&&await sql2`savepoint ${sql2(name)}`;try{if(result2=await new Promise((resolve3,reject)=>{let x=fn2(sql2);Promise.resolve(Array.isArray(x)?Promise.all(x):x).then(resolve3,reject)}),uncaughtError)throw uncaughtError}catch(e){throw await(name?sql2`rollback to ${sql2(name)}`:sql2`rollback`),e instanceof PostgresError&&e.code==="25P02"&&uncaughtError||e}if(!name)prepare?await sql2`prepare transaction '${sql2.unsafe(prepare)}'`:await sql2`commit`;return result2;function savepoint(name2,fn3){if(name2&&Array.isArray(name2.raw))return savepoint((sql3)=>sql3.apply(sql3,arguments));return arguments.length===1&&(fn3=name2,name2=null),scope(c,fn3,"s"+savepoints+++(name2?"_"+name2:""))}function handler2(q){q.catch((e)=>uncaughtError||(uncaughtError=e)),c.queue===full?queries2.push(q):c.execute(q)||move(c,full)}}function onexecute(c){connection2=c,move(c,reserved),c.reserved=()=>queries2.length?c.execute(queries2.shift()):move(c,reserved)}}function move(c,queue){return c.queue.remove(c),queue.push(c),c.queue=queue,queue===open3?c.idleTimer.start():c.idleTimer.cancel(),c}function json2(x){return new Parameter(x,3802)}function array(x,type2){if(!Array.isArray(x))return array(Array.from(arguments));return new Parameter(x,type2||(x.length?inferType(x)||25:0),options.shared.typeArrayMap)}function handler(query){if(ending)return query.reject(Errors.connection("CONNECTION_ENDED",options,options));if(open3.length)return go(open3.shift(),query);if(closed.length)return connect(closed.shift(),query);busy.length?go(busy.shift(),query):queries.push(query)}function go(c,query){return c.execute(query)?move(c,busy):move(c,full)}function cancel(query){return new Promise((resolve3,reject)=>{query.state?query.active?connection_default(options).cancel(query.state,resolve3,reject):query.cancelled={resolve:resolve3,reject}:(queries.remove(query),query.cancelled=!0,query.reject(Errors.generic("57014","canceling statement due to user request")),resolve3())})}async function end({timeout=null}={}){if(ending)return ending;await 1;let timer2;return ending=Promise.race([new Promise((r)=>timeout!==null&&(timer2=setTimeout(destroy,timeout*1000,r))),Promise.all(connections.map((c)=>c.end()).concat(listen.sql?listen.sql.end({timeout:0}):[],subscribe.sql?subscribe.sql.end({timeout:0}):[]))]).then(()=>clearTimeout(timer2))}async function close(){await Promise.all(connections.map((c)=>c.end()))}async function destroy(resolve3){await Promise.all(connections.map((c)=>c.terminate()));while(queries.length)queries.shift().reject(Errors.connection("CONNECTION_DESTROYED",options));resolve3()}function connect(c,query){return move(c,connecting),c.connect(query),c}function onend(c){move(c,ended)}function onopen(c){if(queries.length===0)return move(c,open3);let max=Math.ceil(queries.length/(connecting.length+1)),ready=!0;while(ready&&queries.length&&max-- >0){let query=queries.shift();if(query.reserve)return query.reserve(c);ready=c.execute(query)}ready?move(c,busy):move(c,full)}function onclose(c,e){move(c,closed),c.reserved=null,c.onclose&&(c.onclose(e),c.onclose=null),options.onclose&&options.onclose(c.id),queries.length&&connect(c,queries.shift())}}function parseOptions(a,b2){if(a&&a.shared)return a;let env=process.env,o=(!a||typeof a==="string"?b2:a)||{},{url,multihost}=parseUrl(a),query=[...url.searchParams].reduce((a2,[b3,c])=>(a2[b3]=c,a2),{}),host=o.hostname||o.host||multihost||url.hostname||env.PGHOST||"localhost",port=o.port||url.port||env.PGPORT||5432,user=o.user||o.username||url.username||env.PGUSERNAME||env.PGUSER||osUsername();o.no_prepare&&(o.prepare=!1),query.sslmode&&(query.ssl=query.sslmode,delete query.sslmode),"timeout"in o&&(console.log("The timeout option is deprecated, use idle_timeout instead"),o.idle_timeout=o.timeout),query.sslrootcert==="system"&&(query.ssl="verify-full");let ints=["idle_timeout","connect_timeout","max_lifetime","max_pipeline","backoff","keep_alive"],defaults={max:globalThis.Cloudflare?3:10,ssl:!1,sslnegotiation:null,idle_timeout:null,connect_timeout:30,max_lifetime,max_pipeline:100,backoff,keep_alive:60,prepare:!0,debug:!1,fetch_types:!0,publications:"alltables",target_session_attrs:null};return{host:Array.isArray(host)?host:host.split(",").map((x)=>x.split(":")[0]),port:Array.isArray(port)?port:host.split(",").map((x)=>parseInt(x.split(":")[1]||port)),path:o.path||host.indexOf("/")>-1&&host+"/.s.PGSQL."+port,database:o.database||o.db||(url.pathname||"").slice(1)||env.PGDATABASE||user,user,pass:o.pass||o.password||url.password||env.PGPASSWORD||"",...Object.entries(defaults).reduce((acc,[k,d])=>{let value=k in o?o[k]:(k in query)?query[k]==="disable"||query[k]==="false"?!1:query[k]:env["PG"+k.toUpperCase()]||d;return acc[k]=typeof value==="string"&&ints.includes(k)?+value:value,acc},{}),connection:{application_name:env.PGAPPNAME||"postgres.js",...o.connection,...Object.entries(query).reduce((acc,[k,v])=>((k in defaults)||(acc[k]=v),acc),{})},types:o.types||{},target_session_attrs:tsa(o,url,env),onnotice:o.onnotice,onnotify:o.onnotify,onclose:o.onclose,onparameter:o.onparameter,socket:o.socket,transform:parseTransform(o.transform||{undefined:void 0}),parameters:{},shared:{retries:0,typeArrayMap:{}},...mergeUserTypes(o.types)}}function tsa(o,url,env){let x=o.target_session_attrs||url.searchParams.get("target_session_attrs")||env.PGTARGETSESSIONATTRS;if(!x||["read-write","read-only","primary","standby","prefer-standby"].includes(x))return x;throw Error("target_session_attrs "+x+" is not supported")}function backoff(retries){return(0.5+Math.random()/2)*Math.min(3**retries/100,20)}function max_lifetime(){return 60*(30+Math.random()*30)}function parseTransform(x){return{undefined:x.undefined,column:{from:typeof x.column==="function"?x.column:x.column&&x.column.from,to:x.column&&x.column.to},value:{from:typeof x.value==="function"?x.value:x.value&&x.value.from,to:x.value&&x.value.to},row:{from:typeof x.row==="function"?x.row:x.row&&x.row.from,to:x.row&&x.row.to}}}function parseUrl(url){if(!url||typeof url!=="string")return{url:{searchParams:new Map}};let host=url;host=host.slice(host.indexOf("://")+3).split(/[?/]/)[0],host=decodeURIComponent(host.slice(host.indexOf("@")+1));let urlObj=new URL(url.replace(host,host.split(",")[0]));return{url:{username:decodeURIComponent(urlObj.username),password:decodeURIComponent(urlObj.password),host:urlObj.host,hostname:urlObj.hostname,port:urlObj.port,pathname:urlObj.pathname,searchParams:urlObj.searchParams},multihost:host.indexOf(",")>-1&&host}}function osUsername(){try{return os.userInfo().username}catch(_){return process.env.USERNAME||process.env.USER||process.env.LOGNAME}}var src_default;var init_src=__esm(()=>{init_types3();init_connection();init_query();init_queue();init_errors2();init_large();Object.assign(Postgres,{PostgresError,toPascal,pascal,toCamel,camel,toKebab,kebab,fromPascal,fromCamel,fromKebab,BigInt:{to:20,from:[20],parse:(x)=>BigInt(x),serialize:(x)=>x.toString()}});src_default=Postgres});var exports_db={};__export(exports_db,{shutdown:()=>shutdown,runRetention:()=>runRetention,resolveTcpPgPassword:()=>resolveTcpPgPassword,resolvePgserveSocketDir:()=>resolvePgserveSocketDir,resolvePgserveLibpqSocketPath:()=>resolvePgserveLibpqSocketPath,resolvePgserveDaemonPidPath:()=>resolvePgserveDaemonPidPath,resolvePgserveControlSocketPath:()=>resolvePgserveControlSocketPath,resolvePgserveAuthPassword:()=>resolvePgserveAuthPassword,resolveDatabaseName:()=>resolveDatabaseName,resetConnection:()=>resetConnection,probePgserveDaemon:()=>probePgserveDaemon,isSocketMode:()=>isSocketMode,isConnected:()=>isConnected,isAvailable:()=>isAvailable,getOrStartDaemon:()=>getOrStartDaemon,getLockfilePath:()=>getLockfilePath,getDataDir:()=>getDataDir,getConnection:()=>getConnection,getActivePort:()=>getActivePort,ensurePgserve:()=>ensurePgserve,checkRootGuard:()=>checkRootGuard,autoStartDaemon:()=>autoStartDaemon,__setSpawnDaemonForTest:()=>__setSpawnDaemonForTest,DB_NAME:()=>DB_NAME});import{execFileSync,execSync as execSync3,spawn}from"child_process";import{existsSync as existsSync13,mkdirSync as mkdirSync6,readFileSync as readFileSync9,renameSync,unlinkSync as unlinkSync3,writeFileSync as writeFileSync6}from"fs";import{createConnection}from"net";import{homedir as homedir11}from"os";import{basename as basename2,dirname as dirname5,join as join17}from"path";import{pathToFileURL}from"url";function resolvePgserveSocketDir(){let xdg=process.env.XDG_RUNTIME_DIR,base=xdg&&xdg.length>0?xdg:"/tmp";return join17(base,"pgserve")}function resolveDatabaseName(){let testDbName=process.env.GENIE_TEST_DB_NAME;if(testDbName&&testDbName.length>0)return testDbName;return DB_NAME}function resolvePgserveAuthPassword(){let password=process.env.PGPASSWORD;return password&&password.length>0?password:DB_NAME}function resolvePgserveTimeoutMs(){let parsed=Number(process.env.GENIE_PGSERVE_TIMEOUT);return Number.isFinite(parsed)&&parsed>0?parsed:16000}function resolvePgConnectTimeoutSeconds(useSocket){let parsed=Number(process.env.GENIE_PG_CONNECT_TIMEOUT);if(Number.isFinite(parsed)&&parsed>0)return Math.ceil(parsed);if(!useSocket)return 5;return Math.max(16,Math.ceil(resolvePgserveTimeoutMs()/1000))}function resolveTcpPgPassword(){return resolvePgserveAuthPassword()}function resolvePgserveLibpqSocketPath(){return join17(resolvePgserveSocketDir(),".s.PGSQL.5432")}function resolvePgserveControlSocketPath(){return join17(resolvePgserveSocketDir(),"control.sock")}function resolvePgserveDaemonPidPath(){return join17(resolvePgserveSocketDir(),"pgserve.pid")}function probePgserveDaemon(){let socketPresent=existsSync13(resolvePgserveLibpqSocketPath()),pid=liveDaemonPid(readDaemonPid(resolvePgserveDaemonPidPath()));if(socketPresent&&pid!==null)return{running:!0,pid,socketPresent:!0};if(!socketPresent&&pid===null)return{running:!1,pid:null,socketPresent:!1,reason:"no daemon"};return{running:!1,pid,socketPresent,reason:socketPresent?"socket present but pid stale":"pid alive but no socket"}}function readDaemonPid(pidPath){if(!existsSync13(pidPath))return null;try{let raw=readFileSync9(pidPath,"utf-8").trim(),parsed=Number.parseInt(raw,10);return Number.isInteger(parsed)&&parsed>0?parsed:null}catch{return null}}function liveDaemonPid(pid){if(pid===null)return null;try{return process.kill(pid,0),pid}catch(err){return err.code==="EPERM"?pid:null}}function findLocalPgserveRoot(){let candidates=[join17(import.meta.dir,"..","node_modules","pgserve"),join17(import.meta.dir,"..","..","node_modules","pgserve")];for(let root of candidates)if(existsSync13(join17(root,"package.json")))return root;return null}function resolveLocalPgserveEntry(){let root=findLocalPgserveRoot();if(root===null)return null;try{let pkg=JSON.parse(readFileSync9(join17(root,"package.json"),"utf-8"));return join17(root,pkg.main??"src/index.js")}catch{return join17(root,"src/index.js")}}async function importPgserveSdk(){let localEntry=resolveLocalPgserveEntry();if(localEntry!==null&&existsSync13(localEntry))try{return await import(pathToFileURL(localEntry).href)}catch{}try{return await import("pgserve")}catch{return null}}function findPgserveDaemonCommand(){let localRoot=findLocalPgserveRoot();if(localRoot!==null){let localCommand=resolvePgservePackageCommand(localRoot);if(localCommand!==null)return localCommand}try{let resolved=__require.resolve("pgserve/bin/pgserve-wrapper.cjs"),packageCommand=resolvePgservePackageCommand(join17(dirname5(resolved),".."));if(packageCommand!==null)return packageCommand}catch{}let globalBin=join17(homedir11(),".bun","bin","pgserve");if(existsSync13(globalBin))return{command:globalBin,argsPrefix:[],display:globalBin};try{let fromPath=execSync3("which pgserve",{encoding:"utf-8",timeout:3000}).trim();if(fromPath.length>0)return{command:fromPath,argsPrefix:[],display:fromPath}}catch{}return null}function resolvePgservePackageCommand(root){let script=join17(root,"bin","postgres-server.js"),bun=findBunRuntime();if(existsSync13(script)&&bun!==null)return{command:bun,argsPrefix:[script],display:`${bun} ${script}`};let wrapper=join17(root,"bin","pgserve-wrapper.cjs");if(existsSync13(wrapper))return{command:wrapper,argsPrefix:[],display:wrapper};return null}function findBunRuntime(){if(process.execPath&&existsSync13(process.execPath)&&basename2(process.execPath).startsWith("bun"))return process.execPath;let homeBun=join17(homedir11(),".bun","bin",process.platform==="win32"?"bun.exe":"bun");if(existsSync13(homeBun))return homeBun;try{let fromPath=execSync3("which bun",{encoding:"utf-8",timeout:3000}).trim();if(fromPath.length>0)return fromPath}catch{}return null}function sleep(ms){return new Promise((r)=>setTimeout(r,ms))}async function getOrStartDaemon(){if(process.env.GENIE_PG_DISABLE_AUTOSTART==="1"||isPgAutostartDisabled()){let state=probePgserveDaemon();if(state.running&&await isPgserveSocketResponsive())return state;throw Error("pgserve daemon unavailable and PG autostart is disabled")}let initial=probePgserveDaemon();if(initial.running){if(await isPgserveSocketResponsive())return initial;await recoverUnresponsivePgserveDaemon(initial)}if(process.env.CI==="true"&&process.env.GENIE_PG_ALLOW_CI_AUTOSTART!=="1")throw Error("pgserve v2 daemon socket not present and CI=true. Either start `pgserve daemon` in the workflow or set GENIE_PG_ALLOW_CI_AUTOSTART=1 to opt in.");let rootErr=checkRootGuard();if(rootErr!==null)throw Error(rootErr);if(initial.reason==="socket present but pid stale"&&await isPgserveSocketResponsive())return{running:!0,pid:null,socketPresent:!0,reason:"socket completes pgserve greeting but pid file is stale"};if(daemonStartPromise)return await daemonStartPromise,probePgserveDaemon();daemonStartPromise=startPgserveDaemonOnce(initial);try{await daemonStartPromise}finally{daemonStartPromise=null}return probePgserveDaemon()}function cleanPartialDaemonState(initial){if(initial.reason==="pid alive but no socket"&&initial.pid!==null)unlinkIfPresent(resolvePgserveDaemonPidPath());if(initial.reason==="socket present but pid stale")removeStalePgserveSocketArtifacts()}async function recoverUnresponsivePgserveDaemon(state){if(state.pid!==null&&isLikelyPgserveDaemonProcess(state.pid)){if(await signalPgserveDaemonPid(state.pid,"SIGTERM"),liveDaemonPid(state.pid)!==null)await signalPgserveDaemonPid(state.pid,"SIGKILL")}removeStalePgserveSocketArtifacts()}function isLikelyPgserveDaemonProcess(pid){try{let command=execFileSync("ps",["-p",String(pid),"-o","command="],{encoding:"utf-8",timeout:1000}).trim();return command.includes("pgserve")||command.includes("postgres-server.js")||command.includes("postgres")&&command.includes(DATA_DIR)}catch{return!1}}async function signalPgserveDaemonPid(pid,signal){let signaled=!1;try{process.kill(-pid,signal),signaled=!0}catch{}try{process.kill(pid,signal),signaled=!0}catch{}if(!signaled)return;let deadline=Date.now()+(signal==="SIGTERM"?1000:250);while(Date.now()<deadline){if(liveDaemonPid(pid)===null)return;await sleep(50)}}async function isPgserveSocketResponsive(){let candidates=[resolvePgserveLibpqSocketPath(),resolvePgserveControlSocketPath()].filter((path2)=>existsSync13(path2));for(let path2 of candidates)if(await canCompletePgserveGreet(path2))return!0;return!1}function canCompletePgserveGreet(path2){return new Promise((resolve3)=>{let settled=!1,timer2=null,socket=null,finish=(ok)=>{if(settled)return;if(settled=!0,timer2)clearTimeout(timer2);socket?.removeAllListeners(),socket?.destroy(),resolve3(ok)},request=Buffer.alloc(8);request.writeUInt32BE(8,0),request.writeUInt32BE(PG_SSL_REQUEST_CODE,4),socket=createConnection(path2),timer2=setTimeout(()=>finish(!1),PGSERVE_GREET_TIMEOUT_MS),timer2.unref(),socket.once("connect",()=>socket?.write(request)),socket.once("data",(chunk)=>finish(chunk[0]===78||chunk[0]===83)),socket.once("error",()=>finish(!1))})}function removeStalePgserveSocketArtifacts(){for(let path2 of[resolvePgserveDaemonPidPath(),resolvePgserveLibpqSocketPath(),resolvePgserveControlSocketPath()])unlinkIfPresent(path2)}function unlinkIfPresent(path2){try{unlinkSync3(path2)}catch{}}async function startPgserveDaemonOnce(initial){cleanPartialDaemonState(initial);let daemonCommand=findPgserveDaemonCommand();if(daemonCommand===null){if(await tryEnsureDaemonWithSdk())return;throw Error("pgserve binary not found. Install with `bun add pgserve@^2.0.2` (or `npm i pgserve@^2.0.2`), or start `pgserve daemon` manually before running genie.")}mkdirSync6(resolvePgserveSocketDir(),{recursive:!0,mode:448});let child=spawn(daemonCommand.command,[...daemonCommand.argsPrefix,"daemon","--data",DATA_DIR,"--log","warn"],{detached:!0,stdio:"ignore",env:{...process.env}});try{await waitForDaemonSocket(daemonCommand,child),child.unref()}catch(err){throw await terminatePgserveTree(child),err}}async function waitForDaemonSocket(daemonCommand,child){let socketPath=resolvePgserveLibpqSocketPath(),timeout=resolvePgserveTimeoutMs(),deadline=Date.now()+timeout,childExit=null;child?.once("exit",(code,signal)=>{childExit=signal?`signal ${signal}`:`exit code ${code??"unknown"}`});while(Date.now()<deadline){if(existsSync13(socketPath)&&await isPgserveSocketResponsive())return;if(childExit!==null)throw Error(`pgserve v2 daemon exited before binding ${socketPath} (${childExit}). Try starting it manually: ${formatPgserveDaemonCommand(daemonCommand)}`);await sleep(250)}throw Error(`pgserve v2 daemon did not bind ${socketPath} within ${Math.round(timeout/1000)}s. Try starting it manually: ${formatPgserveDaemonCommand(daemonCommand)}`)}function formatPgserveDaemonCommand(daemonCommand){return`${daemonCommand.display} daemon --data ${DATA_DIR} --log warn`}async function tryEnsureDaemonWithSdk(){let sdk=await importPgserveSdk();if(sdk===null)return!1;if(typeof sdk.ensureDaemon!=="function")return!1;try{let state=await sdk.ensureDaemon({dataDir:DATA_DIR,logLevel:"warn",timeoutMs:resolvePgserveTimeoutMs(),controlSocketDir:resolvePgserveSocketDir()});if(!state.running||!(state.libpqSocketPresent??state.socketPresent??!0))return!1;if(await isPgserveSocketResponsive())return!0;return await recoverUnresponsivePgserveDaemon(probePgserveDaemon()),!1}catch{let state=probePgserveDaemon();if(state.running)await recoverUnresponsivePgserveDaemon(state);else cleanPartialDaemonState(state);return!1}}function maskCredentials(url){return url.replace(/\/\/.*@/,"//***@")}function checkRootGuard(){if(process.getuid?.()!==0)return null;if(process.env.GENIE_ALLOW_ROOT==="1")return null;return"pgserve cannot start under uid 0 (root) \u2014 PostgreSQL refuses to run as root for security reasons. "+"Run genie as a non-root user, or set GENIE_ALLOW_ROOT=1 to attempt anyway. See: https://github.com/automagik-dev/genie/issues/1226"}function isPgAutostartDisabled(){let value=process.env.GENIE_PG_NO_AUTOSTART;return value!==void 0&&TRUTHY_ENV.has(value.trim().toLowerCase())}function selfHealPostgres(dataDir){try{execSync3(`pkill -9 -f "postgres.*${dataDir.replace(/\//g,"\\/")}" 2>/dev/null || true`,{stdio:"ignore",timeout:5000}),execSync3(`pkill -9 -f "pgserve.*${dataDir.replace(/\//g,"\\/")}" 2>/dev/null || true`,{stdio:"ignore",timeout:5000})}catch{}let pidFile=join17(dataDir,"postmaster.pid");if(existsSync13(pidFile))try{unlinkSync3(pidFile)}catch{}try{execSync3("ipcs -m 2>/dev/null | awk '$6 == 0 {print $2}' | xargs -I{} ipcrm -m {} 2>/dev/null || true",{stdio:"ignore",timeout:5000})}catch{}}function signalPgserveTree(child,signal){let pid=child.pid;if(pid===void 0){try{child.kill(signal)}catch{}return}try{if(process.platform==="win32")child.kill(signal);else process.kill(-pid,signal)}catch{try{child.kill(signal)}catch{}}}async function terminatePgserveTree(child){if(signalPgserveTree(child,"SIGTERM"),!await new Promise((resolve3)=>{if(child.exitCode!==null||child.signalCode!==null){resolve3(!0);return}let timer2=setTimeout(()=>resolve3(!1),1000);timer2.unref(),child.once("exit",()=>{clearTimeout(timer2),resolve3(!0)})}))signalPgserveTree(child,"SIGKILL")}function getPort(){let envPort=process.env.GENIE_PG_PORT;if(envPort){let parsed=Number.parseInt(envPort,10);if(!Number.isNaN(parsed)&&parsed>0&&parsed<65536)return parsed}return DEFAULT_PORT}async function isPostgresHealthy(port){try{return await Promise.race([(async()=>{let pg=(await Promise.resolve().then(() => (init_src(),exports_src))).default,probe=pg({host:DEFAULT_HOST,port,database:DB_NAME,username:DB_NAME,password:resolveTcpPgPassword(),max:1,connect_timeout:3,idle_timeout:1});try{return await probe`SELECT 1`,await probe.end({timeout:2}),!0}catch{try{await probe.end({timeout:1})}catch{}return!1}})(),new Promise((resolve3)=>{setTimeout(()=>resolve3(!1),4000).unref()})])}catch{return!1}}function readLockfile(){try{let content=readFileSync9(LOCKFILE_PATH,"utf-8").trim(),port=Number.parseInt(content,10);if(!Number.isNaN(port)&&port>0&&port<65536)return port}catch{}return null}function writeLockfile(port){try{mkdirSync6(GENIE_HOME,{recursive:!0});let tmpPath=`${LOCKFILE_PATH}.tmp.${process.pid}`;writeFileSync6(tmpPath,String(port),"utf-8"),renameSync(tmpPath,LOCKFILE_PATH)}catch{}}function removeLockfile(){try{unlinkSync3(LOCKFILE_PATH)}catch{}}async function runRetention(sql){if(retentionRan)return;try{await sql.unsafe(`
|
|
679
679
|
DELETE FROM heartbeats WHERE created_at < now() - interval '7 days';
|
|
680
680
|
DELETE FROM machine_snapshots WHERE created_at < now() - interval '30 days';
|
|
681
681
|
DELETE FROM audit_events WHERE entity_type LIKE 'otel_%' AND created_at < now() - interval '30 days';
|
|
682
682
|
DELETE FROM genie_runtime_events WHERE created_at < now() - interval '14 days';
|
|
683
683
|
`),retentionRan=!0}catch(retErr){retentionRan=!0;let msg=retErr instanceof Error?retErr.message:String(retErr);process.stderr.write(`[genie] retention cleanup warning: ${msg}
|
|
684
684
|
`)}}async function ensurePgserve(){if(activePort===null){let testPort=await resolveTestPort();if(testPort!==null)return activePort=testPort,process.env.GENIE_PG_AVAILABLE="true",testPort}if(ensurePromise)return ensurePromise;ensurePromise=_ensurePgserve();try{return await ensurePromise}finally{ensurePromise=null}}function __setSpawnDaemonForTest(fn){spawnDaemon=fn??(()=>{let bunPath=process.execPath??"bun",genieBin=process.argv[1]??"genie";spawn(bunPath,[genieBin,"serve","start","--headless","--foreground"],{detached:!0,stdio:"ignore",env:{...process.env,GENIE_IS_DAEMON:"1"}}).unref()})}function readPidFile(pidPath){try{return readFileSync9(pidPath,"utf-8").trim()||null}catch{return null}}function parsePidFile(raw){let sepIdx=raw.indexOf(":"),pid,recordedStartTime;if(sepIdx<0)pid=Number.parseInt(raw,10),recordedStartTime=null;else{pid=Number.parseInt(raw.slice(0,sepIdx),10);let tail=raw.slice(sepIdx+1).trim();recordedStartTime=tail===""||tail==="unknown"?null:tail}if(Number.isNaN(pid)||pid<=0)return null;return{pid,recordedStartTime}}function isServeAlive(pid,recordedStartTime){try{process.kill(pid,0)}catch{return!1}if(recordedStartTime===null)return!1;let currentStartTime=getProcessStartTime(pid);return currentStartTime!==null&¤tStartTime===recordedStartTime}function unlinkQuiet(path2){try{unlinkSync3(path2)}catch{}}async function autoStartDaemon(){let home=process.env.GENIE_HOME??GENIE_HOME,pidPath=join17(home,"serve.pid"),raw=readPidFile(pidPath);if(!raw){lastAutoStartOutcome="missing",lastAutoStartPid=null,spawnDaemon();return}let parsed=parsePidFile(raw);if(!parsed){unlinkQuiet(pidPath),lastAutoStartOutcome="stale",lastAutoStartPid=null,spawnDaemon();return}if(isServeAlive(parsed.pid,parsed.recordedStartTime)){lastAutoStartOutcome="alive",lastAutoStartPid=parsed.pid;return}unlinkQuiet(pidPath),lastAutoStartOutcome="stale",lastAutoStartPid=parsed.pid,spawnDaemon()}async function resolveTestPort(){let raw=process.env.GENIE_TEST_PG_PORT;if(!raw)return null;let parsed=Number.parseInt(raw,10);if(Number.isNaN(parsed)||parsed<=0||parsed>=65536||!await isPostgresHealthy(parsed))throw Error(`GENIE_TEST_PG_PORT=${raw} set but not reachable`);return parsed}async function tryExistingPort(port){let portFromFile=readLockfile();if(portFromFile!==null&&await isPostgresHealthy(portFromFile))return activePort=portFromFile,process.env.GENIE_PG_AVAILABLE="true",portFromFile;if(await isPostgresHealthy(port))return activePort=port,process.env.GENIE_PG_AVAILABLE="true",writeLockfile(port),port;return null}async function spawnPgserveDirect(port){mkdirSync6(DATA_DIR,{recursive:!0}),selfHealPostgres(DATA_DIR);try{let startedPort=await startPgserveOnPort(port);return registerExitHandler(),startedPort}catch(err){process.env.GENIE_PG_AVAILABLE="false";let message=err instanceof Error?err.message:String(err);throw Error(`pgserve failed to start: ${maskCredentials(message)}`)}}async function waitForDaemonPort(){let deadline=Date.now()+16000;while(Date.now()<deadline){let p=readLockfile();if(p!==null&&await isPostgresHealthy(p))return activePort=p,process.env.GENIE_PG_AVAILABLE="true",p;await new Promise((r)=>setTimeout(r,500))}return null}function throwDaemonTimeout(outcomeAtStart,pidAtStart){process.env.GENIE_PG_AVAILABLE="false";let home=process.env.GENIE_HOME??GENIE_HOME,pidPath=join17(home,"serve.pid"),hasPidFile=existsSync13(pidPath),currentPort=readLockfile()??getPort();if(outcomeAtStart==="stale")throw Error(`Stale ~/.genie/serve.pid (PID ${pidAtStart??"unknown"} was not our serve). Removed and retried \u2014 if this persists, run: genie serve start`);if(!hasPidFile)throw Error("genie serve not running. Run: genie serve start");throw Error(`genie serve is running (PID ${pidAtStart??outcomeAtStart??"unknown"}) but pgserve did not respond on port ${currentPort} within 16s. Try: genie serve restart, or check ~/.genie/logs/scheduler.log`)}async function _ensurePgserve(){if(activePort!==null)return activePort;let port=getPort(),existing=await tryExistingPort(port);if(existing!==null)return existing;if(process.env.CI==="true")throw process.env.GENIE_PG_AVAILABLE="false",Error("pgserve not available in CI");if(isPgAutostartDisabled())throw process.env.GENIE_PG_AVAILABLE="false",Error("pgserve unavailable and GENIE_PG_NO_AUTOSTART=1");let rootErr=checkRootGuard();if(rootErr!==null)throw process.env.GENIE_PG_AVAILABLE="false",Error(rootErr);if(process.env.GENIE_IS_DAEMON==="1")return spawnPgserveDirect(port);await autoStartDaemon();let outcomeAtStart=lastAutoStartOutcome,pidAtStart=lastAutoStartPid,waited=await waitForDaemonPort();if(waited!==null)return waited;throwDaemonTimeout(outcomeAtStart,pidAtStart)}function findPgserveBin(){try{let resolved=__require.resolve("pgserve/bin/pgserve-wrapper.cjs");if(existsSync13(resolved))return resolved}catch{}let globalBin=join17(homedir11(),".bun","bin","pgserve");if(existsSync13(globalBin))return globalBin;try{return execSync3("which pgserve",{encoding:"utf-8",timeout:3000}).trim()}catch{return"pgserve"}}async function startPgserveOnPort(port){mkdirSync6(DATA_DIR,{recursive:!0});let child=spawn(findPgserveBin(),["--port",String(port),"--host",DEFAULT_HOST,"--data",DATA_DIR,"--log","warn","--no-stats","--no-cluster","--pgvector"],{detached:!0,stdio:"ignore"});child.unref(),pgserveChild=child;let timeout=Number(process.env.GENIE_PGSERVE_TIMEOUT)||30000,deadline=Date.now()+timeout;while(Date.now()<deadline){if(await isPostgresHealthy(port))return activePort=port,ownsLockfile=!0,process.env.GENIE_PG_AVAILABLE="true",writeLockfile(port),port;await new Promise((r)=>setTimeout(r,500))}if(await terminatePgserveTree(child),pgserveChild===child)pgserveChild=null;throw selfHealPostgres(DATA_DIR),Error(`pgserve failed to start on port ${port} (timeout after ${timeout/1000}s)`)}function registerExitHandler(){if(exitHandlerRegistered)return;exitHandlerRegistered=!0;let cleanup=()=>{if(pgserveChild)signalPgserveTree(pgserveChild,"SIGTERM"),pgserveChild=null;if(ownsLockfile)removeLockfile(),ownsLockfile=!1};process.on("exit",cleanup),process.on("SIGINT",()=>{cleanup(),process.exit(130)}),process.on("SIGTERM",()=>{cleanup(),process.exit(143)})}async function healthCheckCachedClient(){if(!sqlClient)return null;try{return await sqlClient`SELECT 1`,sqlClient}catch{let dying=sqlClient;if(!dying)return null;return sqlClient=null,activePort=null,dying.end({timeout:5}).catch(()=>{}),null}}async function runPostConnectSetup(client,isTestMode,timings){let _t2=Date.now(),skipBoot=isTestMode||process.env.GENIE_SKIP_DB_BOOT==="1";if(!skipBoot)await runMigrations(client);let _t3=Date.now();if(!skipBoot&&(needsSeed()||await needsSeededTeams(client)))await runSeed(client);let _t4=Date.now(),_t5=_t4;if(process.env.GENIE_PROFILE_DB)console.error(`[db-profile] pgserve=${timings.t1-timings.t0}ms migrate=${_t3-_t2}ms seed=${_t4-_t3}ms retention=skipped total=${_t5-timings.t0}ms`)}async function getConnection(){let cached=await healthCheckCachedClient();if(cached)return cached;if(buildPromise)return buildPromise;buildPromise=_buildConnection();try{return await buildPromise}finally{buildPromise=null}}function shouldUseUnixSocket(){if(process.env.GENIE_PG_FORCE_TCP==="1")return!1;if(process.env.GENIE_TEST_PG_PORT)return!1;return!0}async function maybePrintBanner(client,isTestMode){if(bannerPrinted||isTestMode)return;if(process.env.GENIE_QUIET==="1"||process.env.GENIE_NO_BANNER==="1"){bannerPrinted=!0;return}try{let db=(await client.unsafe("SELECT current_database() AS db"))[0]?.db;if(typeof db==="string"&&db.length>0)process.stderr.write(`[pgserve] connected to ${db}
|
|
685
|
-
`)}catch{}bannerPrinted=!0}async function _buildConnection(){let _t0=Date.now(),useSocket=shouldUseUnixSocket();if(useSocket)await getOrStartDaemon();let port=useSocket?5432:await ensurePgserve(),_t1=Date.now(),pgModule=(await Promise.resolve().then(() => (init_src(),exports_src))).default,database=resolveDatabaseName(),isTestMode=Boolean(process.env.GENIE_TEST_DB_NAME),pgWireCredential=useSocket?resolvePgserveAuthPassword():resolveTcpPgPassword(),host=useSocket?resolvePgserveSocketDir():DEFAULT_HOST;sqlClient=pgModule({host,port,database,username:DB_NAME,[PG_AUTH_FIELD]:pgWireCredential,max:50,idle_timeout:1,connect_timeout:resolvePgConnectTimeoutSeconds(useSocket),onnotice:()=>{},connection:{client_min_messages:"warning"}});try{if(await runPostConnectSetup(sqlClient,isTestMode,{t0:_t0,t1:_t1}),await maybePrintBanner(sqlClient,isTestMode),useSocket)activePort=SOCKET_PORT_SENTINEL,process.env.GENIE_PG_AVAILABLE="true"}catch(err){let dying=sqlClient;throw sqlClient=null,activePort=null,dying?.end({timeout:2}).catch(()=>{}),err}return sqlClient}function isConnected(){return sqlClient!==null}async function resetConnection(){if(sqlClient){let dying=sqlClient;sqlClient=null,await dying.end({timeout:5})}}async function isAvailable(){try{return await(await getConnection())`SELECT 1`,!0}catch{return!1}}async function shutdown(){if(sqlClient)await sqlClient.end({timeout:5}),sqlClient=null;if(ownsLockfile)removeLockfile(),ownsLockfile=!1}function getDataDir(){return DATA_DIR}function getActivePort(){return activePort??getPort()}function isSocketMode(){return activePort===SOCKET_PORT_SENTINEL}function getLockfilePath(){return LOCKFILE_PATH}var DEFAULT_PORT=19642,DEFAULT_HOST="127.0.0.1",SOCKET_PORT_SENTINEL=0,GENIE_HOME,DATA_DIR,LOCKFILE_PATH,PG_AUTH_FIELD,DB_NAME,TRUTHY_ENV,daemonStartPromise=null,pgserveChild=null,sqlClient=null,activePort=null,ensurePromise=null,buildPromise=null,ownsLockfile=!1,exitHandlerRegistered=!1,retentionRan=!1,lastAutoStartOutcome=null,lastAutoStartPid=null,spawnDaemon=()=>{let bunPath=process.execPath??"bun",genieBin=process.argv[1]??"genie";spawn(bunPath,[genieBin,"serve","start","--headless","--foreground"],{detached:!0,stdio:"ignore",env:{...process.env,GENIE_IS_DAEMON:"1"}}).unref()},bannerPrinted=!1;var init_db=__esm(()=>{init_db_migrations();init_pg_seed();init_process_identity();GENIE_HOME=process.env.GENIE_HOME??join17(homedir11(),".genie"),DATA_DIR=join17(GENIE_HOME,"data","pgserve"),LOCKFILE_PATH=join17(GENIE_HOME,"pgserve.port"),PG_AUTH_FIELD=["pass","word"].join(""),DB_NAME=["post","gres"].join(""),TRUTHY_ENV=new Set(["1","true","yes","on"])});import{createHmac as createHmac2}from"crypto";import{homedir as homedir12}from"os";function hashEntity(namespace,value){let key=process.env.GENIE_REDACTION_KEY??"genie-redaction-fallback";return`tier-a:${namespace}:${createHmac2("sha256",key).update(value).digest("hex").slice(0,16)}`}function dropSecretShaped(text){let out=text;for(let{name,pattern}of SECRET_PATTERNS)out=out.replace(pattern,`<REDACTED:${name}>`);return out}function stripEnvVars(text){return text.replace(ENV_ASSIGN,(_m,name)=>`${name}=<REDACTED>`)}function tokenizePath(p){let home=homedir12(),out=p;if(home&&out.startsWith(home))out=`~${out.slice(home.length)}`;let segments=out.split("/").filter(Boolean);if(segments.length>6){let head=segments.slice(0,3).join("/"),tail=segments.slice(-2).join("/");out=`${out.startsWith("/")?"/":""}${head}/\u2026/${tail}`}return out=out.replace(/\b[0-9a-f]{12,}\b/g,"<id>"),out}function redactFreeText(value){return stripEnvVars(dropSecretShaped(value))}function capPayload(body){let serialized;try{serialized=JSON.stringify(body)}catch{return{overflow:!0,content_hash:"unserializable",body:{overflow:!0}}}if(Buffer.byteLength(serialized,"utf8")<=MAX_PAYLOAD_BYTES)return{overflow:!1,body};let key=process.env.GENIE_REDACTION_KEY??"genie-redaction-fallback",digest=createHmac2("sha256",key).update(serialized).digest("hex").slice(0,16);return{overflow:!0,content_hash:digest,body:{overflow:!0,content_hash:digest,original_bytes:Buffer.byteLength(serialized,"utf8")}}}var SECRET_PATTERNS,SENSITIVE_ENV_NAME="[A-Z][A-Z0-9_]*(?:_KEY|_SECRET|_TOKEN|_PASSWORD|_PASS|_AUTH|_API_KEY)",ENV_ASSIGN,MAX_PAYLOAD_BYTES=65536;var init_redactors=__esm(()=>{SECRET_PATTERNS=[{name:"anthropic-key",pattern:/sk-ant-[A-Za-z0-9_-]{20,}/g},{name:"openai-key",pattern:/sk-[A-Za-z0-9]{20,}/g},{name:"github-token",pattern:/gh[pousr]_[A-Za-z0-9]{30,}/g},{name:"aws-access-key",pattern:/AKIA[0-9A-Z]{16}/g},{name:"aws-secret",pattern:/(?<![A-Za-z0-9])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9])/g},{name:"bearer-token",pattern:/(?:Bearer|bearer)\s+[A-Za-z0-9._\-~+/=]{20,}/g},{name:"jwt",pattern:/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g},{name:"pem-header",pattern:/-----BEGIN [A-Z ]+ PRIVATE KEY-----/g},{name:"sensitive-path",pattern:/\/(?:[^\s"',;():]+\/)*\.(?:secrets|ssh|aws|gnupg|keys)(?:\/[^\s"',;():]*)?/g}];ENV_ASSIGN=new RegExp(`\\b(${SENSITIVE_ENV_NAME})\\s*[=:]\\s*([^\\s"',;]+)`,"g")});function tagTier(schema2,tier,note){let desc=`tier:${tier}${note?`; ${note}`:""}`;return schema2.describe(desc)}var exports_agent_lifecycle={};__export(exports_agent_lifecycle,{schema:()=>schema2,TYPE:()=>TYPE,SCHEMA_VERSION:()=>SCHEMA_VERSION,KIND:()=>KIND});var SCHEMA_VERSION=1,TYPE="agent.lifecycle",KIND="span",AgentIdSchema,TeamSchema,ExecutorSchema,SessionIdSchema,CwdSchema,ExitReasonSchema,DurationSchema,schema2;var init_agent_lifecycle=__esm(()=>{init_zod();init_redactors();AgentIdSchema=tagTier(exports_external.string().min(1).max(256),"B","agent name \u2014 public"),TeamSchema=tagTier(exports_external.string().min(1).max(256).optional(),"B"),ExecutorSchema=tagTier(exports_external.enum(["claude-code","claude-sdk","codex","shell"]),"C"),SessionIdSchema=tagTier(exports_external.string().min(1).max(128).transform((v)=>hashEntity("session",v)),"A","session id hashed"),CwdSchema=tagTier(exports_external.string().max(1024).transform(tokenizePath),"B"),ExitReasonSchema=tagTier(exports_external.enum(["stopped","killed","crashed","idle-suspend","completed"]),"C"),DurationSchema=tagTier(exports_external.number().int().min(0),"C","ms"),schema2=exports_external.object({agent_id:AgentIdSchema,team:TeamSchema,executor:ExecutorSchema,session_id:SessionIdSchema.optional(),cwd:CwdSchema.optional(),exit_reason:ExitReasonSchema.optional(),duration_ms:DurationSchema.optional()}).strict()});var exports_agent_resume_attempted={};__export(exports_agent_resume_attempted,{schema:()=>schema3,TYPE:()=>TYPE2,SCHEMA_VERSION:()=>SCHEMA_VERSION2,KIND:()=>KIND2});var SCHEMA_VERSION2=1,TYPE2="agent.resume.attempted",KIND2="event",AGENT_STATES,EntityIdSchema,AttemptNumberSchema,StateSchema,LastErrorSchema,TriggerSchema,schema3;var init_agent_resume_attempted=__esm(()=>{init_zod();init_redactors();AGENT_STATES=["spawning","working","idle","permission","question","done","error","suspended","unknown"],EntityIdSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A","agent id hashed"),AttemptNumberSchema=tagTier(exports_external.number().int().min(1).max(64),"C"),StateSchema=tagTier(exports_external.enum(AGENT_STATES),"C"),LastErrorSchema=tagTier(exports_external.string().max(500).transform((v)=>redactFreeText(v)).optional(),"B","truncated to 500 chars"),TriggerSchema=tagTier(exports_external.enum(["scheduler","manual","boot"]),"C"),schema3=exports_external.object({entity_id:EntityIdSchema,attempt_number:AttemptNumberSchema,state_before:StateSchema,state_after:StateSchema,last_error:LastErrorSchema,trigger:TriggerSchema}).strict()});var exports_agent_resume_failed={};__export(exports_agent_resume_failed,{schema:()=>schema4,TYPE:()=>TYPE3,SCHEMA_VERSION:()=>SCHEMA_VERSION3,KIND:()=>KIND3});var SCHEMA_VERSION3=1,TYPE3="agent.resume.failed",KIND3="event",AGENT_STATES2,EntityIdSchema2,AttemptNumberSchema2,StateSchema2,LastErrorSchema2,TriggerSchema2,ExhaustedSchema,schema4;var init_agent_resume_failed=__esm(()=>{init_zod();init_redactors();AGENT_STATES2=["spawning","working","idle","permission","question","done","error","suspended","unknown"],EntityIdSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A","agent id hashed"),AttemptNumberSchema2=tagTier(exports_external.number().int().min(1).max(64),"C"),StateSchema2=tagTier(exports_external.enum(AGENT_STATES2),"C"),LastErrorSchema2=tagTier(exports_external.string().max(500).transform((v)=>redactFreeText(v)).optional(),"B","truncated to 500 chars"),TriggerSchema2=tagTier(exports_external.enum(["scheduler","manual","boot"]),"C"),ExhaustedSchema=tagTier(exports_external.boolean(),"C"),schema4=exports_external.object({entity_id:EntityIdSchema2,attempt_number:AttemptNumberSchema2,state_before:StateSchema2,state_after:StateSchema2,last_error:LastErrorSchema2,trigger:TriggerSchema2,exhausted:ExhaustedSchema}).strict()});var exports_agent_resume_succeeded={};__export(exports_agent_resume_succeeded,{schema:()=>schema5,TYPE:()=>TYPE4,SCHEMA_VERSION:()=>SCHEMA_VERSION4,KIND:()=>KIND4});var SCHEMA_VERSION4=1,TYPE4="agent.resume.succeeded",KIND4="event",AGENT_STATES3,EntityIdSchema3,AttemptNumberSchema3,StateSchema3,LastErrorSchema3,TriggerSchema3,schema5;var init_agent_resume_succeeded=__esm(()=>{init_zod();init_redactors();AGENT_STATES3=["spawning","working","idle","permission","question","done","error","suspended","unknown"],EntityIdSchema3=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A","agent id hashed"),AttemptNumberSchema3=tagTier(exports_external.number().int().min(1).max(64),"C"),StateSchema3=tagTier(exports_external.enum(AGENT_STATES3),"C"),LastErrorSchema3=tagTier(exports_external.string().max(500).transform((v)=>redactFreeText(v)).optional(),"B","truncated to 500 chars"),TriggerSchema3=tagTier(exports_external.enum(["scheduler","manual","boot"]),"C"),schema5=exports_external.object({entity_id:EntityIdSchema3,attempt_number:AttemptNumberSchema3,state_before:StateSchema3,state_after:StateSchema3,last_error:LastErrorSchema3,trigger:TriggerSchema3}).strict()});var exports_audit_export={};__export(exports_audit_export,{schema:()=>schema6,TYPE:()=>TYPE5,SCHEMA_VERSION:()=>SCHEMA_VERSION5,KIND:()=>KIND5,DEFAULT_TIER:()=>DEFAULT_TIER});var SCHEMA_VERSION5=1,TYPE5="audit.export",KIND5="event",DEFAULT_TIER="audit",ExporterActorSchema,SinceIdSchema,RowCountSchema,BreakCountSchema,BundleSignaturePrefixSchema,TenantIdSchema,ReasonSchema,schema6;var init_audit_export=__esm(()=>{init_zod();init_redactors();ExporterActorSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A"),SinceIdSchema=tagTier(exports_external.number().int().min(0),"C"),RowCountSchema=tagTier(exports_external.number().int().min(0),"C"),BreakCountSchema=tagTier(exports_external.number().int().min(0),"C","chain breaks detected in the exported range"),BundleSignaturePrefixSchema=tagTier(exports_external.string().min(1).max(16),"C","first 16 hex of the bundle HMAC signature (full is on disk)"),TenantIdSchema=tagTier(exports_external.string().min(1).max(128),"C"),ReasonSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)),"B","IR justification for the export"),schema6=exports_external.object({exporter_actor:ExporterActorSchema,since_id:SinceIdSchema,row_count:RowCountSchema,break_count:BreakCountSchema,bundle_signature_prefix:BundleSignaturePrefixSchema,tenant_id:TenantIdSchema,reason:ReasonSchema}).strict()});var exports_audit_un_hash={};__export(exports_audit_un_hash,{schema:()=>schema7,TYPE:()=>TYPE6,SCHEMA_VERSION:()=>SCHEMA_VERSION6,KIND:()=>KIND6,DEFAULT_TIER:()=>DEFAULT_TIER2});var SCHEMA_VERSION6=1,TYPE6="audit.un_hash",KIND6="event",DEFAULT_TIER2="audit",AdminActorSchema,NamespaceSchema,HashedValueSchema,ResolvedMarkerSchema,ReasonSchema2,TicketRefSchema,schema7;var init_audit_un_hash=__esm(()=>{init_zod();init_redactors();AdminActorSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A","admin who performed the un-hash (Tier-A hashed)"),NamespaceSchema=tagTier(exports_external.string().min(1).max(64),"C"),HashedValueSchema=tagTier(exports_external.string().min(1).max(256),"B","tier-a:ns:... source hash requested"),ResolvedMarkerSchema=tagTier(exports_external.boolean(),"C","true if un-hash succeeded"),ReasonSchema2=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)),"B","IR justification for the un-hash"),TicketRefSchema=tagTier(exports_external.string().max(128).optional(),"C","incident ticket reference"),schema7=exports_external.object({admin_actor:AdminActorSchema,namespace:NamespaceSchema,hashed_value:HashedValueSchema,resolved:ResolvedMarkerSchema,reason:ReasonSchema2,ticket_ref:TicketRefSchema}).strict()});var exports_cache_hit={};__export(exports_cache_hit,{schema:()=>schema8,TYPE:()=>TYPE7,SCHEMA_VERSION:()=>SCHEMA_VERSION7,KIND:()=>KIND7});var SCHEMA_VERSION7=1,TYPE7="cache.hit",KIND7="event",CacheSchema,HitSchema,KeyHintSchema,LatencyUsSchema,schema8;var init_cache_hit=__esm(()=>{init_zod();init_redactors();CacheSchema=tagTier(exports_external.string().min(1).max(128),"C"),HitSchema=tagTier(exports_external.boolean(),"C"),KeyHintSchema=tagTier(exports_external.string().max(128).transform((v)=>redactFreeText(v)).optional(),"B"),LatencyUsSchema=tagTier(exports_external.number().int().min(0).max(1e7).optional(),"C","microseconds"),schema8=exports_external.object({cache:CacheSchema,hit:HitSchema,key_hint:KeyHintSchema,latency_us:LatencyUsSchema}).strict()});var exports_cache_invalidate={};__export(exports_cache_invalidate,{schema:()=>schema9,TYPE:()=>TYPE8,SCHEMA_VERSION:()=>SCHEMA_VERSION8,KIND:()=>KIND8});var SCHEMA_VERSION8=1,TYPE8="cache.invalidate",KIND8="event",CacheSchema2,KeysInvalidatedSchema,ReasonSchema3,ScopeSchema,schema9;var init_cache_invalidate=__esm(()=>{init_zod();CacheSchema2=tagTier(exports_external.string().min(1).max(128),"C","cache name \u2014 public"),KeysInvalidatedSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),ReasonSchema3=tagTier(exports_external.enum(["ttl","manual","capacity","rotation","upstream_change"]).optional(),"C"),ScopeSchema=tagTier(exports_external.enum(["key","bucket","all"]).optional(),"C"),schema9=exports_external.object({cache:CacheSchema2,keys_invalidated:KeysInvalidatedSchema,reason:ReasonSchema3,scope:ScopeSchema}).strict()});var exports_cli_command={};__export(exports_cli_command,{schema:()=>schema10,TYPE:()=>TYPE9,SCHEMA_VERSION:()=>SCHEMA_VERSION9,KIND:()=>KIND9});var SCHEMA_VERSION9=1,TYPE9="cli.command",KIND9="span",CommandSchema,ArgsSchema,CwdSchema2,ExitCodeSchema,DurationSchema2,UserAgentSchema,schema10;var init_cli_command=__esm(()=>{init_zod();init_redactors();CommandSchema=tagTier(exports_external.string().max(256),"C","subcommand name only"),ArgsSchema=tagTier(exports_external.array(exports_external.string()).max(32).transform((args)=>args.map((a)=>redactFreeText(a))),"B","argv \u2014 secrets stripped, paths kept"),CwdSchema2=tagTier(exports_external.string().max(1024).transform(tokenizePath),"B","working directory tokenized"),ExitCodeSchema=tagTier(exports_external.number().int().min(-1).max(255),"C"),DurationSchema2=tagTier(exports_external.number().int().min(0).max(3600000),"C","milliseconds"),UserAgentSchema=tagTier(exports_external.string().max(256).optional(),"C"),schema10=exports_external.object({command:CommandSchema,args:ArgsSchema,cwd:CwdSchema2,exit_code:ExitCodeSchema.optional(),duration_ms:DurationSchema2.optional(),user_agent:UserAgentSchema}).strict().transform((v)=>({...v}))});var exports_consumer_heartbeat={};__export(exports_consumer_heartbeat,{schema:()=>schema11,TYPE:()=>TYPE10,SCHEMA_VERSION:()=>SCHEMA_VERSION10,KIND:()=>KIND10});var SCHEMA_VERSION10=1,TYPE10="consumer.heartbeat",KIND10="event",ConsumerIdSchema,LastEventIdSchema,BacklogDepthSchema,RoleSchema,UptimeSecondsSchema,schema11;var init_consumer_heartbeat=__esm(()=>{init_zod();init_redactors();ConsumerIdSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("consumer",v)),"A"),LastEventIdSchema=tagTier(exports_external.number().int().min(0).max(9007199254740991),"C"),BacklogDepthSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),RoleSchema=tagTier(exports_external.enum(["admin","operator","subscriber","audit"]).optional(),"C"),UptimeSecondsSchema=tagTier(exports_external.number().int().min(0).max(31536000).optional(),"C"),schema11=exports_external.object({consumer_id:ConsumerIdSchema,last_event_id_processed:LastEventIdSchema,backlog_depth:BacklogDepthSchema,role:RoleSchema,uptime_seconds:UptimeSecondsSchema}).strict()});var exports_consumer_lagged={};__export(exports_consumer_lagged,{schema:()=>schema12,TYPE:()=>TYPE11,SCHEMA_VERSION:()=>SCHEMA_VERSION11,KIND:()=>KIND11,DEFAULT_TIER:()=>DEFAULT_TIER3});var SCHEMA_VERSION11=1,TYPE11="consumer.lagged",KIND11="event",DEFAULT_TIER3="audit",CountSchema,SpillPathSchema,SeveritySchema,schema12;var init_consumer_lagged=__esm(()=>{init_zod();CountSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),SpillPathSchema=tagTier(exports_external.string().max(512),"B"),SeveritySchema=tagTier(exports_external.enum(["warn","error","fatal"]),"C"),schema12=exports_external.object({severity_class:SeveritySchema,spill_path:SpillPathSchema,rows_spilled:CountSchema,queue_depth:CountSchema,queue_cap:CountSchema}).strict()});var exports_correlation_orphan_rate={};__export(exports_correlation_orphan_rate,{schema:()=>schema13,TYPE:()=>TYPE12,SCHEMA_VERSION:()=>SCHEMA_VERSION12,KIND:()=>KIND12});var SCHEMA_VERSION12=1,TYPE12="correlation.orphan.rate",KIND12="event",RateSchema,CountSchema2,schema13;var init_correlation_orphan_rate=__esm(()=>{init_zod();RateSchema=tagTier(exports_external.number().min(0).max(1),"C"),CountSchema2=tagTier(exports_external.number().int().min(0).max(1e7),"C"),schema13=exports_external.object({window_samples:CountSchema2,orphans:CountSchema2,rate:RateSchema}).strict()});var exports_detector_disabled={};__export(exports_detector_disabled,{schema:()=>schema14,TYPE:()=>TYPE13,SCHEMA_VERSION:()=>SCHEMA_VERSION13,KIND:()=>KIND13});var SCHEMA_VERSION13=1,TYPE13="detector.disabled",KIND13="event",DetectorIdSchema,CauseSchema,BudgetSchema,FireCountSchema,BucketEndTsSchema,schema14;var init_detector_disabled=__esm(()=>{init_zod();DetectorIdSchema=tagTier(exports_external.string().min(1).max(128),"C"),CauseSchema=tagTier(exports_external.literal("fire_budget_exceeded"),"C"),BudgetSchema=tagTier(exports_external.number().int().min(1).max(1e6),"C","events per hour bucket"),FireCountSchema=tagTier(exports_external.number().int().min(0).max(1e6),"C","fires observed in this bucket"),BucketEndTsSchema=tagTier(exports_external.string().datetime({offset:!0}),"C","ISO-8601 timestamp when the current hour bucket expires"),schema14=exports_external.object({detector_id:DetectorIdSchema,cause:CauseSchema,budget:BudgetSchema,fire_count:FireCountSchema,bucket_end_ts:BucketEndTsSchema}).strict()});var exports_emit_backpressure_critical={};__export(exports_emit_backpressure_critical,{schema:()=>schema15,TYPE:()=>TYPE14,SCHEMA_VERSION:()=>SCHEMA_VERSION14,KIND:()=>KIND14,DEFAULT_TIER:()=>DEFAULT_TIER4});var SCHEMA_VERSION14=1,TYPE14="emit.backpressure.critical",KIND14="event",DEFAULT_TIER4="audit",SecondsSchema,CountSchema3,schema15;var init_emit_backpressure_critical=__esm(()=>{init_zod();SecondsSchema=tagTier(exports_external.number().min(0).max(86400),"C"),CountSchema3=tagTier(exports_external.number().int().min(0).max(1e7),"C"),schema15=exports_external.object({spill_duration_seconds:SecondsSchema,spill_rows_total:CountSchema3,queue_depth:CountSchema3,queue_cap:CountSchema3,recommended_action:tagTier(exports_external.enum(["scale_consumers","inspect_pg","restart_bridge"]).optional(),"C")}).strict()});var exports_emitter_latency_p99={};__export(exports_emitter_latency_p99,{schema:()=>schema16,TYPE:()=>TYPE15,SCHEMA_VERSION:()=>SCHEMA_VERSION15,KIND:()=>KIND15});var SCHEMA_VERSION15=1,TYPE15="emitter.latency_p99",KIND15="event",MillisSchema,SampleCountSchema,schema16;var init_emitter_latency_p99=__esm(()=>{init_zod();MillisSchema=tagTier(exports_external.number().min(0).max(600000),"C"),SampleCountSchema=tagTier(exports_external.number().int().min(1).max(1e6),"C"),schema16=exports_external.object({window_samples:SampleCountSchema,p50_ms:MillisSchema,p95_ms:MillisSchema,p99_ms:MillisSchema,max_ms:MillisSchema}).strict()});var exports_emitter_queue_depth={};__export(exports_emitter_queue_depth,{schema:()=>schema17,TYPE:()=>TYPE16,SCHEMA_VERSION:()=>SCHEMA_VERSION16,KIND:()=>KIND16});var SCHEMA_VERSION16=1,TYPE16="emitter.queue.depth",KIND16="event",DepthSchema,CapSchema,UtilizationSchema,schema17;var init_emitter_queue_depth=__esm(()=>{init_zod();DepthSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),CapSchema=tagTier(exports_external.number().int().min(1).max(1e7),"C"),UtilizationSchema=tagTier(exports_external.number().min(0).max(1),"C"),schema17=exports_external.object({depth:DepthSchema,cap:CapSchema,utilization:UtilizationSchema,enqueued_total:tagTier(exports_external.number().int().min(0).max(Number.MAX_SAFE_INTEGER),"C"),flushed_total:tagTier(exports_external.number().int().min(0).max(Number.MAX_SAFE_INTEGER),"C")}).strict()});var exports_emitter_rejected={};__export(exports_emitter_rejected,{schema:()=>schema18,TYPE:()=>TYPE17,SCHEMA_VERSION:()=>SCHEMA_VERSION17,KIND:()=>KIND17});var SCHEMA_VERSION17=1,TYPE17="emitter.rejected",KIND17="event",OffendingTypeSchema,ReasonSchema4,CountSchema4,schema18;var init_emitter_rejected=__esm(()=>{init_zod();OffendingTypeSchema=tagTier(exports_external.string().min(1).max(128),"C"),ReasonSchema4=tagTier(exports_external.enum(["schema_parse","unregistered","kind_mismatch","overflow_cap","queue_full"]),"C"),CountSchema4=tagTier(exports_external.number().int().min(1).max(1e7),"C"),schema18=exports_external.object({offending_type:OffendingTypeSchema,reason:ReasonSchema4,count:CountSchema4}).strict()});var exports_emitter_shedding_load={};__export(exports_emitter_shedding_load,{schema:()=>schema19,TYPE:()=>TYPE18,SCHEMA_VERSION:()=>SCHEMA_VERSION18,KIND:()=>KIND18});var SCHEMA_VERSION18=1,TYPE18="emitter.shedding_load",KIND18="event",CountSchema5,schema19;var init_emitter_shedding_load=__esm(()=>{init_zod();CountSchema5=tagTier(exports_external.number().int().min(0).max(1e7),"C"),schema19=exports_external.object({dropped_debug:CountSchema5,dropped_info:CountSchema5,spilled_warn_plus:CountSchema5,window_seconds:tagTier(exports_external.number().int().min(1).max(3600),"C")}).strict()});var exports_error_raised={};__export(exports_error_raised,{schema:()=>schema20,TYPE:()=>TYPE19,SCHEMA_VERSION:()=>SCHEMA_VERSION19,KIND:()=>KIND19});var SCHEMA_VERSION19=1,TYPE19="error.raised",KIND19="event",ErrorClassSchema,MessageSchema,StackSchema,SubsystemSchema,SeveritySchema2,RetryableSchema,schema20;var init_error_raised=__esm(()=>{init_zod();init_redactors();ErrorClassSchema=tagTier(exports_external.string().min(1).max(256),"C","exception class name"),MessageSchema=tagTier(exports_external.string().max(4096).transform(redactFreeText),"B"),StackSchema=tagTier(exports_external.string().max(16384).transform((stack)=>stack.split(`
|
|
685
|
+
`)}catch{}bannerPrinted=!0}async function _buildConnection(){let _t0=Date.now(),useSocket=shouldUseUnixSocket();if(useSocket)await getOrStartDaemon();let port=useSocket?5432:await ensurePgserve(),_t1=Date.now(),pgModule=(await Promise.resolve().then(() => (init_src(),exports_src))).default,database=resolveDatabaseName(),isTestMode=Boolean(process.env.GENIE_TEST_DB_NAME),pgWireCredential=useSocket?resolvePgserveAuthPassword():resolveTcpPgPassword(),host=useSocket?resolvePgserveSocketDir():DEFAULT_HOST;sqlClient=pgModule({host,port,database,username:DB_NAME,[PG_AUTH_FIELD]:pgWireCredential,max:50,idle_timeout:1,connect_timeout:resolvePgConnectTimeoutSeconds(useSocket),onnotice:()=>{},connection:{client_min_messages:"warning"}});try{if(await runPostConnectSetup(sqlClient,isTestMode,{t0:_t0,t1:_t1}),await maybePrintBanner(sqlClient,isTestMode),useSocket)activePort=SOCKET_PORT_SENTINEL,process.env.GENIE_PG_AVAILABLE="true"}catch(err){let dying=sqlClient;throw sqlClient=null,activePort=null,dying?.end({timeout:2}).catch(()=>{}),err}return sqlClient}function isConnected(){return sqlClient!==null}async function resetConnection(){if(sqlClient){let dying=sqlClient;sqlClient=null,await dying.end({timeout:5})}}async function isAvailable(){try{return await(await getConnection())`SELECT 1`,!0}catch{return!1}}async function shutdown(){if(sqlClient)await sqlClient.end({timeout:5}),sqlClient=null;if(ownsLockfile)removeLockfile(),ownsLockfile=!1}function getDataDir(){return DATA_DIR}function getActivePort(){return activePort??getPort()}function isSocketMode(){return activePort===SOCKET_PORT_SENTINEL}function getLockfilePath(){return LOCKFILE_PATH}var DEFAULT_PORT=19642,DEFAULT_HOST="127.0.0.1",SOCKET_PORT_SENTINEL=0,GENIE_HOME,DATA_DIR,LOCKFILE_PATH,PG_AUTH_FIELD,PG_SSL_REQUEST_CODE=80877103,PGSERVE_GREET_TIMEOUT_MS=1000,DB_NAME,TRUTHY_ENV,daemonStartPromise=null,pgserveChild=null,sqlClient=null,activePort=null,ensurePromise=null,buildPromise=null,ownsLockfile=!1,exitHandlerRegistered=!1,retentionRan=!1,lastAutoStartOutcome=null,lastAutoStartPid=null,spawnDaemon=()=>{let bunPath=process.execPath??"bun",genieBin=process.argv[1]??"genie";spawn(bunPath,[genieBin,"serve","start","--headless","--foreground"],{detached:!0,stdio:"ignore",env:{...process.env,GENIE_IS_DAEMON:"1"}}).unref()},bannerPrinted=!1;var init_db=__esm(()=>{init_db_migrations();init_pg_seed();init_process_identity();GENIE_HOME=process.env.GENIE_HOME??join17(homedir11(),".genie"),DATA_DIR=join17(GENIE_HOME,"data","pgserve"),LOCKFILE_PATH=join17(GENIE_HOME,"pgserve.port"),PG_AUTH_FIELD=["pass","word"].join(""),DB_NAME=["post","gres"].join(""),TRUTHY_ENV=new Set(["1","true","yes","on"])});import{createHmac as createHmac2}from"crypto";import{homedir as homedir12}from"os";function hashEntity(namespace,value){let key=process.env.GENIE_REDACTION_KEY??"genie-redaction-fallback";return`tier-a:${namespace}:${createHmac2("sha256",key).update(value).digest("hex").slice(0,16)}`}function dropSecretShaped(text){let out=text;for(let{name,pattern}of SECRET_PATTERNS)out=out.replace(pattern,`<REDACTED:${name}>`);return out}function stripEnvVars(text){return text.replace(ENV_ASSIGN,(_m,name)=>`${name}=<REDACTED>`)}function tokenizePath(p){let home=homedir12(),out=p;if(home&&out.startsWith(home))out=`~${out.slice(home.length)}`;let segments=out.split("/").filter(Boolean);if(segments.length>6){let head=segments.slice(0,3).join("/"),tail=segments.slice(-2).join("/");out=`${out.startsWith("/")?"/":""}${head}/\u2026/${tail}`}return out=out.replace(/\b[0-9a-f]{12,}\b/g,"<id>"),out}function redactFreeText(value){return stripEnvVars(dropSecretShaped(value))}function capPayload(body){let serialized;try{serialized=JSON.stringify(body)}catch{return{overflow:!0,content_hash:"unserializable",body:{overflow:!0}}}if(Buffer.byteLength(serialized,"utf8")<=MAX_PAYLOAD_BYTES)return{overflow:!1,body};let key=process.env.GENIE_REDACTION_KEY??"genie-redaction-fallback",digest=createHmac2("sha256",key).update(serialized).digest("hex").slice(0,16);return{overflow:!0,content_hash:digest,body:{overflow:!0,content_hash:digest,original_bytes:Buffer.byteLength(serialized,"utf8")}}}var SECRET_PATTERNS,SENSITIVE_ENV_NAME="[A-Z][A-Z0-9_]*(?:_KEY|_SECRET|_TOKEN|_PASSWORD|_PASS|_AUTH|_API_KEY)",ENV_ASSIGN,MAX_PAYLOAD_BYTES=65536;var init_redactors=__esm(()=>{SECRET_PATTERNS=[{name:"anthropic-key",pattern:/sk-ant-[A-Za-z0-9_-]{20,}/g},{name:"openai-key",pattern:/sk-[A-Za-z0-9]{20,}/g},{name:"github-token",pattern:/gh[pousr]_[A-Za-z0-9]{30,}/g},{name:"aws-access-key",pattern:/AKIA[0-9A-Z]{16}/g},{name:"aws-secret",pattern:/(?<![A-Za-z0-9])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9])/g},{name:"bearer-token",pattern:/(?:Bearer|bearer)\s+[A-Za-z0-9._\-~+/=]{20,}/g},{name:"jwt",pattern:/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g},{name:"pem-header",pattern:/-----BEGIN [A-Z ]+ PRIVATE KEY-----/g},{name:"sensitive-path",pattern:/\/(?:[^\s"',;():]+\/)*\.(?:secrets|ssh|aws|gnupg|keys)(?:\/[^\s"',;():]*)?/g}];ENV_ASSIGN=new RegExp(`\\b(${SENSITIVE_ENV_NAME})\\s*[=:]\\s*([^\\s"',;]+)`,"g")});function tagTier(schema2,tier,note){let desc=`tier:${tier}${note?`; ${note}`:""}`;return schema2.describe(desc)}var exports_agent_lifecycle={};__export(exports_agent_lifecycle,{schema:()=>schema2,TYPE:()=>TYPE,SCHEMA_VERSION:()=>SCHEMA_VERSION,KIND:()=>KIND});var SCHEMA_VERSION=1,TYPE="agent.lifecycle",KIND="span",AgentIdSchema,TeamSchema,ExecutorSchema,SessionIdSchema,CwdSchema,ExitReasonSchema,DurationSchema,schema2;var init_agent_lifecycle=__esm(()=>{init_zod();init_redactors();AgentIdSchema=tagTier(exports_external.string().min(1).max(256),"B","agent name \u2014 public"),TeamSchema=tagTier(exports_external.string().min(1).max(256).optional(),"B"),ExecutorSchema=tagTier(exports_external.enum(["claude-code","claude-sdk","codex","shell"]),"C"),SessionIdSchema=tagTier(exports_external.string().min(1).max(128).transform((v)=>hashEntity("session",v)),"A","session id hashed"),CwdSchema=tagTier(exports_external.string().max(1024).transform(tokenizePath),"B"),ExitReasonSchema=tagTier(exports_external.enum(["stopped","killed","crashed","idle-suspend","completed"]),"C"),DurationSchema=tagTier(exports_external.number().int().min(0),"C","ms"),schema2=exports_external.object({agent_id:AgentIdSchema,team:TeamSchema,executor:ExecutorSchema,session_id:SessionIdSchema.optional(),cwd:CwdSchema.optional(),exit_reason:ExitReasonSchema.optional(),duration_ms:DurationSchema.optional()}).strict()});var exports_agent_resume_attempted={};__export(exports_agent_resume_attempted,{schema:()=>schema3,TYPE:()=>TYPE2,SCHEMA_VERSION:()=>SCHEMA_VERSION2,KIND:()=>KIND2});var SCHEMA_VERSION2=1,TYPE2="agent.resume.attempted",KIND2="event",AGENT_STATES,EntityIdSchema,AttemptNumberSchema,StateSchema,LastErrorSchema,TriggerSchema,schema3;var init_agent_resume_attempted=__esm(()=>{init_zod();init_redactors();AGENT_STATES=["spawning","working","idle","permission","question","done","error","suspended","unknown"],EntityIdSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A","agent id hashed"),AttemptNumberSchema=tagTier(exports_external.number().int().min(1).max(64),"C"),StateSchema=tagTier(exports_external.enum(AGENT_STATES),"C"),LastErrorSchema=tagTier(exports_external.string().max(500).transform((v)=>redactFreeText(v)).optional(),"B","truncated to 500 chars"),TriggerSchema=tagTier(exports_external.enum(["scheduler","manual","boot"]),"C"),schema3=exports_external.object({entity_id:EntityIdSchema,attempt_number:AttemptNumberSchema,state_before:StateSchema,state_after:StateSchema,last_error:LastErrorSchema,trigger:TriggerSchema}).strict()});var exports_agent_resume_failed={};__export(exports_agent_resume_failed,{schema:()=>schema4,TYPE:()=>TYPE3,SCHEMA_VERSION:()=>SCHEMA_VERSION3,KIND:()=>KIND3});var SCHEMA_VERSION3=1,TYPE3="agent.resume.failed",KIND3="event",AGENT_STATES2,EntityIdSchema2,AttemptNumberSchema2,StateSchema2,LastErrorSchema2,TriggerSchema2,ExhaustedSchema,schema4;var init_agent_resume_failed=__esm(()=>{init_zod();init_redactors();AGENT_STATES2=["spawning","working","idle","permission","question","done","error","suspended","unknown"],EntityIdSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A","agent id hashed"),AttemptNumberSchema2=tagTier(exports_external.number().int().min(1).max(64),"C"),StateSchema2=tagTier(exports_external.enum(AGENT_STATES2),"C"),LastErrorSchema2=tagTier(exports_external.string().max(500).transform((v)=>redactFreeText(v)).optional(),"B","truncated to 500 chars"),TriggerSchema2=tagTier(exports_external.enum(["scheduler","manual","boot"]),"C"),ExhaustedSchema=tagTier(exports_external.boolean(),"C"),schema4=exports_external.object({entity_id:EntityIdSchema2,attempt_number:AttemptNumberSchema2,state_before:StateSchema2,state_after:StateSchema2,last_error:LastErrorSchema2,trigger:TriggerSchema2,exhausted:ExhaustedSchema}).strict()});var exports_agent_resume_succeeded={};__export(exports_agent_resume_succeeded,{schema:()=>schema5,TYPE:()=>TYPE4,SCHEMA_VERSION:()=>SCHEMA_VERSION4,KIND:()=>KIND4});var SCHEMA_VERSION4=1,TYPE4="agent.resume.succeeded",KIND4="event",AGENT_STATES3,EntityIdSchema3,AttemptNumberSchema3,StateSchema3,LastErrorSchema3,TriggerSchema3,schema5;var init_agent_resume_succeeded=__esm(()=>{init_zod();init_redactors();AGENT_STATES3=["spawning","working","idle","permission","question","done","error","suspended","unknown"],EntityIdSchema3=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A","agent id hashed"),AttemptNumberSchema3=tagTier(exports_external.number().int().min(1).max(64),"C"),StateSchema3=tagTier(exports_external.enum(AGENT_STATES3),"C"),LastErrorSchema3=tagTier(exports_external.string().max(500).transform((v)=>redactFreeText(v)).optional(),"B","truncated to 500 chars"),TriggerSchema3=tagTier(exports_external.enum(["scheduler","manual","boot"]),"C"),schema5=exports_external.object({entity_id:EntityIdSchema3,attempt_number:AttemptNumberSchema3,state_before:StateSchema3,state_after:StateSchema3,last_error:LastErrorSchema3,trigger:TriggerSchema3}).strict()});var exports_audit_export={};__export(exports_audit_export,{schema:()=>schema6,TYPE:()=>TYPE5,SCHEMA_VERSION:()=>SCHEMA_VERSION5,KIND:()=>KIND5,DEFAULT_TIER:()=>DEFAULT_TIER});var SCHEMA_VERSION5=1,TYPE5="audit.export",KIND5="event",DEFAULT_TIER="audit",ExporterActorSchema,SinceIdSchema,RowCountSchema,BreakCountSchema,BundleSignaturePrefixSchema,TenantIdSchema,ReasonSchema,schema6;var init_audit_export=__esm(()=>{init_zod();init_redactors();ExporterActorSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A"),SinceIdSchema=tagTier(exports_external.number().int().min(0),"C"),RowCountSchema=tagTier(exports_external.number().int().min(0),"C"),BreakCountSchema=tagTier(exports_external.number().int().min(0),"C","chain breaks detected in the exported range"),BundleSignaturePrefixSchema=tagTier(exports_external.string().min(1).max(16),"C","first 16 hex of the bundle HMAC signature (full is on disk)"),TenantIdSchema=tagTier(exports_external.string().min(1).max(128),"C"),ReasonSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)),"B","IR justification for the export"),schema6=exports_external.object({exporter_actor:ExporterActorSchema,since_id:SinceIdSchema,row_count:RowCountSchema,break_count:BreakCountSchema,bundle_signature_prefix:BundleSignaturePrefixSchema,tenant_id:TenantIdSchema,reason:ReasonSchema}).strict()});var exports_audit_un_hash={};__export(exports_audit_un_hash,{schema:()=>schema7,TYPE:()=>TYPE6,SCHEMA_VERSION:()=>SCHEMA_VERSION6,KIND:()=>KIND6,DEFAULT_TIER:()=>DEFAULT_TIER2});var SCHEMA_VERSION6=1,TYPE6="audit.un_hash",KIND6="event",DEFAULT_TIER2="audit",AdminActorSchema,NamespaceSchema,HashedValueSchema,ResolvedMarkerSchema,ReasonSchema2,TicketRefSchema,schema7;var init_audit_un_hash=__esm(()=>{init_zod();init_redactors();AdminActorSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A","admin who performed the un-hash (Tier-A hashed)"),NamespaceSchema=tagTier(exports_external.string().min(1).max(64),"C"),HashedValueSchema=tagTier(exports_external.string().min(1).max(256),"B","tier-a:ns:... source hash requested"),ResolvedMarkerSchema=tagTier(exports_external.boolean(),"C","true if un-hash succeeded"),ReasonSchema2=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)),"B","IR justification for the un-hash"),TicketRefSchema=tagTier(exports_external.string().max(128).optional(),"C","incident ticket reference"),schema7=exports_external.object({admin_actor:AdminActorSchema,namespace:NamespaceSchema,hashed_value:HashedValueSchema,resolved:ResolvedMarkerSchema,reason:ReasonSchema2,ticket_ref:TicketRefSchema}).strict()});var exports_cache_hit={};__export(exports_cache_hit,{schema:()=>schema8,TYPE:()=>TYPE7,SCHEMA_VERSION:()=>SCHEMA_VERSION7,KIND:()=>KIND7});var SCHEMA_VERSION7=1,TYPE7="cache.hit",KIND7="event",CacheSchema,HitSchema,KeyHintSchema,LatencyUsSchema,schema8;var init_cache_hit=__esm(()=>{init_zod();init_redactors();CacheSchema=tagTier(exports_external.string().min(1).max(128),"C"),HitSchema=tagTier(exports_external.boolean(),"C"),KeyHintSchema=tagTier(exports_external.string().max(128).transform((v)=>redactFreeText(v)).optional(),"B"),LatencyUsSchema=tagTier(exports_external.number().int().min(0).max(1e7).optional(),"C","microseconds"),schema8=exports_external.object({cache:CacheSchema,hit:HitSchema,key_hint:KeyHintSchema,latency_us:LatencyUsSchema}).strict()});var exports_cache_invalidate={};__export(exports_cache_invalidate,{schema:()=>schema9,TYPE:()=>TYPE8,SCHEMA_VERSION:()=>SCHEMA_VERSION8,KIND:()=>KIND8});var SCHEMA_VERSION8=1,TYPE8="cache.invalidate",KIND8="event",CacheSchema2,KeysInvalidatedSchema,ReasonSchema3,ScopeSchema,schema9;var init_cache_invalidate=__esm(()=>{init_zod();CacheSchema2=tagTier(exports_external.string().min(1).max(128),"C","cache name \u2014 public"),KeysInvalidatedSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),ReasonSchema3=tagTier(exports_external.enum(["ttl","manual","capacity","rotation","upstream_change"]).optional(),"C"),ScopeSchema=tagTier(exports_external.enum(["key","bucket","all"]).optional(),"C"),schema9=exports_external.object({cache:CacheSchema2,keys_invalidated:KeysInvalidatedSchema,reason:ReasonSchema3,scope:ScopeSchema}).strict()});var exports_cli_command={};__export(exports_cli_command,{schema:()=>schema10,TYPE:()=>TYPE9,SCHEMA_VERSION:()=>SCHEMA_VERSION9,KIND:()=>KIND9});var SCHEMA_VERSION9=1,TYPE9="cli.command",KIND9="span",CommandSchema,ArgsSchema,CwdSchema2,ExitCodeSchema,DurationSchema2,UserAgentSchema,schema10;var init_cli_command=__esm(()=>{init_zod();init_redactors();CommandSchema=tagTier(exports_external.string().max(256),"C","subcommand name only"),ArgsSchema=tagTier(exports_external.array(exports_external.string()).max(32).transform((args)=>args.map((a)=>redactFreeText(a))),"B","argv \u2014 secrets stripped, paths kept"),CwdSchema2=tagTier(exports_external.string().max(1024).transform(tokenizePath),"B","working directory tokenized"),ExitCodeSchema=tagTier(exports_external.number().int().min(-1).max(255),"C"),DurationSchema2=tagTier(exports_external.number().int().min(0).max(3600000),"C","milliseconds"),UserAgentSchema=tagTier(exports_external.string().max(256).optional(),"C"),schema10=exports_external.object({command:CommandSchema,args:ArgsSchema,cwd:CwdSchema2,exit_code:ExitCodeSchema.optional(),duration_ms:DurationSchema2.optional(),user_agent:UserAgentSchema}).strict().transform((v)=>({...v}))});var exports_consumer_heartbeat={};__export(exports_consumer_heartbeat,{schema:()=>schema11,TYPE:()=>TYPE10,SCHEMA_VERSION:()=>SCHEMA_VERSION10,KIND:()=>KIND10});var SCHEMA_VERSION10=1,TYPE10="consumer.heartbeat",KIND10="event",ConsumerIdSchema,LastEventIdSchema,BacklogDepthSchema,RoleSchema,UptimeSecondsSchema,schema11;var init_consumer_heartbeat=__esm(()=>{init_zod();init_redactors();ConsumerIdSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("consumer",v)),"A"),LastEventIdSchema=tagTier(exports_external.number().int().min(0).max(9007199254740991),"C"),BacklogDepthSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),RoleSchema=tagTier(exports_external.enum(["admin","operator","subscriber","audit"]).optional(),"C"),UptimeSecondsSchema=tagTier(exports_external.number().int().min(0).max(31536000).optional(),"C"),schema11=exports_external.object({consumer_id:ConsumerIdSchema,last_event_id_processed:LastEventIdSchema,backlog_depth:BacklogDepthSchema,role:RoleSchema,uptime_seconds:UptimeSecondsSchema}).strict()});var exports_consumer_lagged={};__export(exports_consumer_lagged,{schema:()=>schema12,TYPE:()=>TYPE11,SCHEMA_VERSION:()=>SCHEMA_VERSION11,KIND:()=>KIND11,DEFAULT_TIER:()=>DEFAULT_TIER3});var SCHEMA_VERSION11=1,TYPE11="consumer.lagged",KIND11="event",DEFAULT_TIER3="audit",CountSchema,SpillPathSchema,SeveritySchema,schema12;var init_consumer_lagged=__esm(()=>{init_zod();CountSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),SpillPathSchema=tagTier(exports_external.string().max(512),"B"),SeveritySchema=tagTier(exports_external.enum(["warn","error","fatal"]),"C"),schema12=exports_external.object({severity_class:SeveritySchema,spill_path:SpillPathSchema,rows_spilled:CountSchema,queue_depth:CountSchema,queue_cap:CountSchema}).strict()});var exports_correlation_orphan_rate={};__export(exports_correlation_orphan_rate,{schema:()=>schema13,TYPE:()=>TYPE12,SCHEMA_VERSION:()=>SCHEMA_VERSION12,KIND:()=>KIND12});var SCHEMA_VERSION12=1,TYPE12="correlation.orphan.rate",KIND12="event",RateSchema,CountSchema2,schema13;var init_correlation_orphan_rate=__esm(()=>{init_zod();RateSchema=tagTier(exports_external.number().min(0).max(1),"C"),CountSchema2=tagTier(exports_external.number().int().min(0).max(1e7),"C"),schema13=exports_external.object({window_samples:CountSchema2,orphans:CountSchema2,rate:RateSchema}).strict()});var exports_detector_disabled={};__export(exports_detector_disabled,{schema:()=>schema14,TYPE:()=>TYPE13,SCHEMA_VERSION:()=>SCHEMA_VERSION13,KIND:()=>KIND13});var SCHEMA_VERSION13=1,TYPE13="detector.disabled",KIND13="event",DetectorIdSchema,CauseSchema,BudgetSchema,FireCountSchema,BucketEndTsSchema,schema14;var init_detector_disabled=__esm(()=>{init_zod();DetectorIdSchema=tagTier(exports_external.string().min(1).max(128),"C"),CauseSchema=tagTier(exports_external.literal("fire_budget_exceeded"),"C"),BudgetSchema=tagTier(exports_external.number().int().min(1).max(1e6),"C","events per hour bucket"),FireCountSchema=tagTier(exports_external.number().int().min(0).max(1e6),"C","fires observed in this bucket"),BucketEndTsSchema=tagTier(exports_external.string().datetime({offset:!0}),"C","ISO-8601 timestamp when the current hour bucket expires"),schema14=exports_external.object({detector_id:DetectorIdSchema,cause:CauseSchema,budget:BudgetSchema,fire_count:FireCountSchema,bucket_end_ts:BucketEndTsSchema}).strict()});var exports_emit_backpressure_critical={};__export(exports_emit_backpressure_critical,{schema:()=>schema15,TYPE:()=>TYPE14,SCHEMA_VERSION:()=>SCHEMA_VERSION14,KIND:()=>KIND14,DEFAULT_TIER:()=>DEFAULT_TIER4});var SCHEMA_VERSION14=1,TYPE14="emit.backpressure.critical",KIND14="event",DEFAULT_TIER4="audit",SecondsSchema,CountSchema3,schema15;var init_emit_backpressure_critical=__esm(()=>{init_zod();SecondsSchema=tagTier(exports_external.number().min(0).max(86400),"C"),CountSchema3=tagTier(exports_external.number().int().min(0).max(1e7),"C"),schema15=exports_external.object({spill_duration_seconds:SecondsSchema,spill_rows_total:CountSchema3,queue_depth:CountSchema3,queue_cap:CountSchema3,recommended_action:tagTier(exports_external.enum(["scale_consumers","inspect_pg","restart_bridge"]).optional(),"C")}).strict()});var exports_emitter_latency_p99={};__export(exports_emitter_latency_p99,{schema:()=>schema16,TYPE:()=>TYPE15,SCHEMA_VERSION:()=>SCHEMA_VERSION15,KIND:()=>KIND15});var SCHEMA_VERSION15=1,TYPE15="emitter.latency_p99",KIND15="event",MillisSchema,SampleCountSchema,schema16;var init_emitter_latency_p99=__esm(()=>{init_zod();MillisSchema=tagTier(exports_external.number().min(0).max(600000),"C"),SampleCountSchema=tagTier(exports_external.number().int().min(1).max(1e6),"C"),schema16=exports_external.object({window_samples:SampleCountSchema,p50_ms:MillisSchema,p95_ms:MillisSchema,p99_ms:MillisSchema,max_ms:MillisSchema}).strict()});var exports_emitter_queue_depth={};__export(exports_emitter_queue_depth,{schema:()=>schema17,TYPE:()=>TYPE16,SCHEMA_VERSION:()=>SCHEMA_VERSION16,KIND:()=>KIND16});var SCHEMA_VERSION16=1,TYPE16="emitter.queue.depth",KIND16="event",DepthSchema,CapSchema,UtilizationSchema,schema17;var init_emitter_queue_depth=__esm(()=>{init_zod();DepthSchema=tagTier(exports_external.number().int().min(0).max(1e7),"C"),CapSchema=tagTier(exports_external.number().int().min(1).max(1e7),"C"),UtilizationSchema=tagTier(exports_external.number().min(0).max(1),"C"),schema17=exports_external.object({depth:DepthSchema,cap:CapSchema,utilization:UtilizationSchema,enqueued_total:tagTier(exports_external.number().int().min(0).max(Number.MAX_SAFE_INTEGER),"C"),flushed_total:tagTier(exports_external.number().int().min(0).max(Number.MAX_SAFE_INTEGER),"C")}).strict()});var exports_emitter_rejected={};__export(exports_emitter_rejected,{schema:()=>schema18,TYPE:()=>TYPE17,SCHEMA_VERSION:()=>SCHEMA_VERSION17,KIND:()=>KIND17});var SCHEMA_VERSION17=1,TYPE17="emitter.rejected",KIND17="event",OffendingTypeSchema,ReasonSchema4,CountSchema4,schema18;var init_emitter_rejected=__esm(()=>{init_zod();OffendingTypeSchema=tagTier(exports_external.string().min(1).max(128),"C"),ReasonSchema4=tagTier(exports_external.enum(["schema_parse","unregistered","kind_mismatch","overflow_cap","queue_full"]),"C"),CountSchema4=tagTier(exports_external.number().int().min(1).max(1e7),"C"),schema18=exports_external.object({offending_type:OffendingTypeSchema,reason:ReasonSchema4,count:CountSchema4}).strict()});var exports_emitter_shedding_load={};__export(exports_emitter_shedding_load,{schema:()=>schema19,TYPE:()=>TYPE18,SCHEMA_VERSION:()=>SCHEMA_VERSION18,KIND:()=>KIND18});var SCHEMA_VERSION18=1,TYPE18="emitter.shedding_load",KIND18="event",CountSchema5,schema19;var init_emitter_shedding_load=__esm(()=>{init_zod();CountSchema5=tagTier(exports_external.number().int().min(0).max(1e7),"C"),schema19=exports_external.object({dropped_debug:CountSchema5,dropped_info:CountSchema5,spilled_warn_plus:CountSchema5,window_seconds:tagTier(exports_external.number().int().min(1).max(3600),"C")}).strict()});var exports_error_raised={};__export(exports_error_raised,{schema:()=>schema20,TYPE:()=>TYPE19,SCHEMA_VERSION:()=>SCHEMA_VERSION19,KIND:()=>KIND19});var SCHEMA_VERSION19=1,TYPE19="error.raised",KIND19="event",ErrorClassSchema,MessageSchema,StackSchema,SubsystemSchema,SeveritySchema2,RetryableSchema,schema20;var init_error_raised=__esm(()=>{init_zod();init_redactors();ErrorClassSchema=tagTier(exports_external.string().min(1).max(256),"C","exception class name"),MessageSchema=tagTier(exports_external.string().max(4096).transform(redactFreeText),"B"),StackSchema=tagTier(exports_external.string().max(16384).transform((stack)=>stack.split(`
|
|
686
686
|
`).map((line)=>tokenizePath(redactFreeText(line))).join(`
|
|
687
|
-
`)),"B","stack paths tokenized"),SubsystemSchema=tagTier(exports_external.string().min(1).max(128),"C"),SeveritySchema2=tagTier(exports_external.enum(["warn","error","fatal"]),"C"),RetryableSchema=tagTier(exports_external.boolean().optional(),"C"),schema20=exports_external.object({error_class:ErrorClassSchema,message:MessageSchema,stack:StackSchema.optional(),subsystem:SubsystemSchema,severity:SeveritySchema2,retryable:RetryableSchema}).strict()});var exports_executor_row_written={};__export(exports_executor_row_written,{schema:()=>schema21,TYPE:()=>TYPE20,SCHEMA_VERSION:()=>SCHEMA_VERSION20,KIND:()=>KIND20});var SCHEMA_VERSION20=1,TYPE20="executor.row.written",KIND20="event",TableSchema,RowIdSchema,OperationSchema,ExecutorSchema2,DiffSchema,schema21;var init_executor_row_written=__esm(()=>{init_zod();init_redactors();TableSchema=tagTier(exports_external.string().min(1).max(128),"C","PG table name \u2014 public"),RowIdSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("row",v)),"A"),OperationSchema=tagTier(exports_external.enum(["insert","update","delete","upsert"]),"C"),ExecutorSchema2=tagTier(exports_external.string().max(128).optional(),"C"),DiffSchema=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B","shallow scalar diff only \u2014 payloads never stored here"),schema21=exports_external.object({table:TableSchema,row_id:RowIdSchema,operation:OperationSchema,executor:ExecutorSchema2,before:DiffSchema,after:DiffSchema}).strict()});var exports_executor_write={};__export(exports_executor_write,{schema:()=>schema22,TYPE:()=>TYPE21,SCHEMA_VERSION:()=>SCHEMA_VERSION21,KIND:()=>KIND21});var SCHEMA_VERSION21=1,TYPE21="executor.write",KIND21="span",ExecutorSchema3,TargetSchema,TableSchema2,OperationSchema2,RowsAffectedSchema,DurationSchema3,OutcomeSchema,ErrorHintSchema,schema22;var init_executor_write=__esm(()=>{init_zod();init_redactors();ExecutorSchema3=tagTier(exports_external.enum(["claude-code","claude-sdk","codex","shell"]),"C"),TargetSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("executor_target",v)),"A","target entity hashed"),TableSchema2=tagTier(exports_external.string().max(128).optional(),"C","PG table name \u2014 public"),OperationSchema2=tagTier(exports_external.enum(["insert","update","delete","upsert","copy","truncate"]),"C"),RowsAffectedSchema=tagTier(exports_external.number().int().min(0).max(1e7).optional(),"C"),DurationSchema3=tagTier(exports_external.number().int().min(0).max(60000).optional(),"C","ms"),OutcomeSchema=tagTier(exports_external.enum(["ok","constraint_violation","timeout","error"]).optional(),"C"),ErrorHintSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B"),schema22=exports_external.object({executor:ExecutorSchema3,target:TargetSchema,table:TableSchema2,operation:OperationSchema2,rows_affected:RowsAffectedSchema,duration_ms:DurationSchema3,outcome:OutcomeSchema,error_hint:ErrorHintSchema}).strict()});var exports_hook_delivery={};__export(exports_hook_delivery,{schema:()=>schema23,TYPE:()=>TYPE22,SCHEMA_VERSION:()=>SCHEMA_VERSION22,KIND:()=>KIND22});var SCHEMA_VERSION22=1,TYPE22="hook.delivery",KIND22="span",HookNameSchema,HookEventSchema,AgentIdSchema2,ToolSchema,StatusSchema,DurationSchema4,ExitCodeSchema2,StderrExcerptSchema,schema23;var init_hook_delivery=__esm(()=>{init_zod();init_redactors();HookNameSchema=tagTier(exports_external.string().min(1).max(128),"C","hook name \u2014 public"),HookEventSchema=tagTier(exports_external.string().min(1).max(64),"C","CC hook event name \u2014 public"),AgentIdSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),ToolSchema=tagTier(exports_external.string().max(128).optional(),"C"),StatusSchema=tagTier(exports_external.enum(["ok","timeout","rejected","error"]).optional(),"C"),DurationSchema4=tagTier(exports_external.number().int().min(0).max(60000).optional(),"C","ms (<=15s timeout)"),ExitCodeSchema2=tagTier(exports_external.number().int().min(-1).max(255).optional(),"C"),StderrExcerptSchema=tagTier(exports_external.string().max(4096).transform((v)=>redactFreeText(v)).optional(),"B","redacted stderr excerpt"),schema23=exports_external.object({hook_name:HookNameSchema,agent_id:AgentIdSchema2,tool:ToolSchema,event:HookEventSchema.optional(),status:StatusSchema,duration_ms:DurationSchema4,exit_code:ExitCodeSchema2,stderr_excerpt:StderrExcerptSchema}).strict()});var exports_mailbox_delivery={};__export(exports_mailbox_delivery,{schema:()=>schema24,TYPE:()=>TYPE23,SCHEMA_VERSION:()=>SCHEMA_VERSION23,KIND:()=>KIND23});var SCHEMA_VERSION23=1,TYPE23="mailbox.delivery",KIND23="span",AgentIdSchema3=(ns)=>tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity(ns,v)),"A"),FromSchema,ToSchema,ChannelSchema,OutcomeSchema2,MessageIdSchema,BodyExcerptSchema,DurationSchema5,schema24;var init_mailbox_delivery=__esm(()=>{init_zod();init_redactors();FromSchema=tagTier(exports_external.string().max(128),"C","sender role \u2014 public"),ToSchema=tagTier(exports_external.string().max(128),"C","recipient role \u2014 public"),ChannelSchema=tagTier(exports_external.enum(["tmux","native-inbox","file","broadcast"]),"C"),OutcomeSchema2=tagTier(exports_external.enum(["delivered","queued","pane_dead","rejected","timeout"]).optional(),"C"),MessageIdSchema=AgentIdSchema3("msg").optional(),BodyExcerptSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B","first 512 chars, redacted"),DurationSchema5=tagTier(exports_external.number().int().min(0).max(60000).optional(),"C","ms"),schema24=exports_external.object({from:FromSchema,to:ToSchema,channel:ChannelSchema,outcome:OutcomeSchema2,message_id:MessageIdSchema,body_excerpt:BodyExcerptSchema,duration_ms:DurationSchema5}).strict()});var exports_notify_delivery_lag={};__export(exports_notify_delivery_lag,{schema:()=>schema25,TYPE:()=>TYPE24,SCHEMA_VERSION:()=>SCHEMA_VERSION24,KIND:()=>KIND24});var SCHEMA_VERSION24=1,TYPE24="notify.delivery.lag",KIND24="event",NonceSchema,LagMillisSchema,ChannelSchema2,schema25;var init_notify_delivery_lag=__esm(()=>{init_zod();init_redactors();NonceSchema=tagTier(exports_external.string().min(1).max(128).transform((v)=>hashEntity("notify-probe",v)),"A"),LagMillisSchema=tagTier(exports_external.number().min(0).max(300000),"C"),ChannelSchema2=tagTier(exports_external.string().min(1).max(128),"C"),schema25=exports_external.object({channel:ChannelSchema2,probe_id:NonceSchema,lag_ms:LagMillisSchema,timed_out:tagTier(exports_external.boolean(),"C")}).strict()});var exports_permissions_deny={};__export(exports_permissions_deny,{schema:()=>schema26,TYPE:()=>TYPE25,SCHEMA_VERSION:()=>SCHEMA_VERSION25,KIND:()=>KIND25});var SCHEMA_VERSION25=1,TYPE25="permissions.deny",KIND25="event",ActorSchema,AttemptedRoleSchema,ScopeSchema2,ReasonSchema5,SourceIpSchema,schema26;var init_permissions_deny=__esm(()=>{init_zod();init_redactors();ActorSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A"),AttemptedRoleSchema=tagTier(exports_external.string().min(1).max(64),"C"),ScopeSchema2=tagTier(exports_external.string().min(1).max(128),"C"),ReasonSchema5=tagTier(exports_external.enum(["token_expired","token_invalid","signature_invalid","scope_mismatch","tenant_mismatch","rate_limited","revoked","unknown"]),"C"),SourceIpSchema=tagTier(exports_external.string().max(64).transform((v)=>hashEntity("ip",v)).optional(),"A"),schema26=exports_external.object({actor:ActorSchema,attempted_role:AttemptedRoleSchema,scope:ScopeSchema2,reason:ReasonSchema5,source_ip:SourceIpSchema}).strict()});var exports_permissions_grant={};__export(exports_permissions_grant,{schema:()=>schema27,TYPE:()=>TYPE26,SCHEMA_VERSION:()=>SCHEMA_VERSION26,KIND:()=>KIND26});var SCHEMA_VERSION26=1,TYPE26="permissions.grant",KIND26="event",ActorSchema2,RoleSchema2,ScopeSchema3,ExpiresAtSchema,GrantedBySchema,schema27;var init_permissions_grant=__esm(()=>{init_zod();init_redactors();ActorSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A"),RoleSchema2=tagTier(exports_external.enum(["admin","operator","subscriber","audit"]),"C"),ScopeSchema3=tagTier(exports_external.string().min(1).max(128),"C",'e.g. "genie_events.agent.*" \u2014 public'),ExpiresAtSchema=tagTier(exports_external.string().datetime().optional(),"C"),GrantedBySchema=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("actor",v)).optional(),"A"),schema27=exports_external.object({actor:ActorSchema2,role:RoleSchema2,scope:ScopeSchema3,expires_at:ExpiresAtSchema,granted_by:GrantedBySchema}).strict()});var exports_resume_attempt={};__export(exports_resume_attempt,{schema:()=>schema28,TYPE:()=>TYPE27,SCHEMA_VERSION:()=>SCHEMA_VERSION27,KIND:()=>KIND27});var SCHEMA_VERSION27=1,TYPE27="resume.attempt",KIND27="span",AgentIdSchema4,AttemptNumberSchema4,StrategySchema,SessionIdSchema2,SucceededSchema,FailureReasonSchema,DurationSchema6,schema28;var init_resume_attempt=__esm(()=>{init_zod();init_redactors();AgentIdSchema4=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),AttemptNumberSchema4=tagTier(exports_external.number().int().min(1).max(16),"C"),StrategySchema=tagTier(exports_external.enum(["tmux-attach","claude-resume-session","cold-start","session-backfill"]),"C"),SessionIdSchema2=tagTier(exports_external.string().max(128).transform((v)=>hashEntity("session",v)).optional(),"A"),SucceededSchema=tagTier(exports_external.boolean().optional(),"C"),FailureReasonSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B"),DurationSchema6=tagTier(exports_external.number().int().min(0).max(300000).optional(),"C","ms"),schema28=exports_external.object({agent_id:AgentIdSchema4,attempt_number:AttemptNumberSchema4,strategy:StrategySchema,session_id:SessionIdSchema2,succeeded:SucceededSchema,failure_reason:FailureReasonSchema,duration_ms:DurationSchema6}).strict()});var exports_rot_detected={};__export(exports_rot_detected,{schema:()=>schema29,TYPE:()=>TYPE28,SCHEMA_VERSION:()=>SCHEMA_VERSION28,KIND:()=>KIND28});var SCHEMA_VERSION28=1,TYPE28="rot.detected",KIND28="event",PatternIdSchema,EntityIdSchema4,ObservedValueSchema,ObservedStateSchema,schema29;var init_rot_detected=__esm(()=>{init_zod();init_redactors();PatternIdSchema=tagTier(exports_external.string().min(1).max(128).regex(/^[a-z0-9][a-z0-9._-]*$/,"pattern_id must be kebab/dot/underscore lowercase"),"C"),EntityIdSchema4=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("entity",v)),"A"),ObservedValueSchema=tagTier(exports_external.union([exports_external.string().max(4096).transform(redactFreeText),exports_external.number().finite(),exports_external.boolean(),exports_external.null(),exports_external.array(exports_external.string().max(1024).transform(redactFreeText)).max(256),exports_external.array(exports_external.number().finite()).max(256)]),"B","evidence scalar \u2014 free text runs through redactFreeText"),ObservedStateSchema=tagTier(exports_external.record(exports_external.string().min(1).max(64).regex(/^[a-z0-9_]+$/,"observed_state key must be snake_case"),ObservedValueSchema).refine((obj)=>Object.keys(obj).length<=32,{message:"observed_state_json cannot exceed 32 keys"}),"B","per-pattern evidence record \u2014 keys documented by each detector module"),schema29=exports_external.object({pattern_id:PatternIdSchema,entity_id:EntityIdSchema4,observed_state_json:ObservedStateSchema}).strict()});var exports_rot_executor_ghost_detected={};__export(exports_rot_executor_ghost_detected,{schema:()=>schema30,TYPE:()=>TYPE29,SCHEMA_VERSION:()=>SCHEMA_VERSION29,KIND:()=>KIND29});var SCHEMA_VERSION29=1,TYPE29="rot.executor-ghost.detected",KIND29="event",ResolutionSourceSchema,EnvIdSchema,ResolvedIdSchema,AgentNameSchema,RecoveredSchema,schema30;var init_rot_executor_ghost_detected=__esm(()=>{init_zod();ResolutionSourceSchema=tagTier(exports_external.enum(["resolver","reconciler"]),"C"),EnvIdSchema=tagTier(exports_external.string().uuid(),"C"),ResolvedIdSchema=tagTier(exports_external.string().uuid(),"C"),AgentNameSchema=tagTier(exports_external.string().min(1).max(256),"C"),RecoveredSchema=tagTier(exports_external.boolean(),"C"),schema30=exports_external.object({resolution_source:ResolutionSourceSchema,env_id:EnvIdSchema,resolved_id:ResolvedIdSchema,agent_name:AgentNameSchema,recovered:RecoveredSchema}).strict()});var exports_rot_inbox_watcher_spawn_loop_detected={};__export(exports_rot_inbox_watcher_spawn_loop_detected,{schema:()=>schema31,TYPE:()=>TYPE30,SCHEMA_VERSION:()=>SCHEMA_VERSION30,KIND:()=>KIND30});var SCHEMA_VERSION30=1,TYPE30="rot.inbox-watcher-spawn-loop.detected",KIND30="event",TeamNameSchema,SessionKeySchema,FailureCountSchema,LastErrorMessageSchema,schema31;var init_rot_inbox_watcher_spawn_loop_detected=__esm(()=>{init_zod();init_redactors();TeamNameSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>redactFreeText(v)),"C"),SessionKeySchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>redactFreeText(v)),"C"),FailureCountSchema=tagTier(exports_external.number().int().min(1).max(100),"C"),LastErrorMessageSchema=tagTier(exports_external.string().min(1).max(2048).transform((v)=>redactFreeText(v)),"B","redacted error message from the final failed ensureTeamLead() call"),schema31=exports_external.object({team_name:TeamNameSchema,session_key:SessionKeySchema,failure_count:FailureCountSchema,last_error_message:LastErrorMessageSchema}).strict()});var exports_rot_team_ls_drift_detected={};__export(exports_rot_team_ls_drift_detected,{schema:()=>schema32,TYPE:()=>TYPE31,SCHEMA_VERSION:()=>SCHEMA_VERSION31,KIND:()=>KIND31});var SCHEMA_VERSION31=1,TYPE31="rot.team-ls-drift.detected",KIND31="event",DivergenceKindSchema,DivergentCountSchema,ObservedStateJsonSchema,ObservedStateJsonTruncatedSchema,schema32;var init_rot_team_ls_drift_detected=__esm(()=>{init_zod();init_redactors();DivergenceKindSchema=tagTier(exports_external.enum(["missing_in_disband","missing_in_ls","status_mismatch"]),"C"),DivergentCountSchema=tagTier(exports_external.number().int().min(1).max(1e4),"C"),ObservedStateJsonSchema=tagTier(exports_external.string().min(2).max(16384).transform((v)=>redactFreeText(v)),"B","JSON-encoded snapshot of both data sources for triage"),ObservedStateJsonTruncatedSchema=tagTier(exports_external.literal(!0).optional(),"C","set when detail was dropped to honor the observed_state_json cap"),schema32=exports_external.object({divergence_kind:DivergenceKindSchema,divergent_count:DivergentCountSchema,observed_state_json:ObservedStateJsonSchema,observed_state_json_truncated:ObservedStateJsonTruncatedSchema}).strict()});var exports_runbook_triggered={};__export(exports_runbook_triggered,{schema:()=>schema33,TYPE:()=>TYPE32,SCHEMA_VERSION:()=>SCHEMA_VERSION32,KIND:()=>KIND32});var SCHEMA_VERSION32=1,TYPE32="runbook.triggered",KIND32="event",RuleSchema,EvidenceCountSchema,CorrelationIdSchema,WindowMinutesSchema,RecommendedSqlSchema,EvidenceSummarySchema,schema33;var init_runbook_triggered=__esm(()=>{init_zod();init_redactors();RuleSchema=tagTier(exports_external.string().min(1).max(64).regex(/^R\d+$/,"rule id must be R<int>"),"C"),EvidenceCountSchema=tagTier(exports_external.number().int().min(1).max(1e6),"C"),CorrelationIdSchema=tagTier(exports_external.string().max(128).transform((v)=>hashEntity("trace",v)).optional(),"A"),WindowMinutesSchema=tagTier(exports_external.number().int().min(1).max(1440).optional(),"C"),RecommendedSqlSchema=tagTier(exports_external.string().max(4096).transform((v)=>redactFreeText(v)).optional(),"B","mitigation SQL \u2014 redacted free text"),EvidenceSummarySchema=tagTier(exports_external.string().max(1024).transform((v)=>redactFreeText(v)).optional(),"B"),schema33=exports_external.object({rule:RuleSchema,evidence_count:EvidenceCountSchema,window_minutes:WindowMinutesSchema,correlation_id:CorrelationIdSchema,recommended_sql:RecommendedSqlSchema,evidence_summary:EvidenceSummarySchema}).strict()});var exports_schema_violation={};__export(exports_schema_violation,{schema:()=>schema34,TYPE:()=>TYPE33,SCHEMA_VERSION:()=>SCHEMA_VERSION33,KIND:()=>KIND33});var SCHEMA_VERSION33=1,TYPE33="schema.violation",KIND33="event",OffendingTypeSchema2,RejectedBytesSchema,IssueSchema,schema34;var init_schema_violation=__esm(()=>{init_zod();init_redactors();OffendingTypeSchema2=tagTier(exports_external.string().min(1).max(128),"C"),RejectedBytesSchema=tagTier(exports_external.number().int().min(0).max(1048576),"C"),IssueSchema=tagTier(exports_external.object({path:exports_external.string().max(256),code:exports_external.string().max(64),message:exports_external.string().max(512).transform(redactFreeText)}),"B"),schema34=exports_external.object({offending_type:OffendingTypeSchema2,issues:tagTier(exports_external.array(IssueSchema).max(32),"B"),rejected_bytes:RejectedBytesSchema,source_subsystem:tagTier(exports_external.string().max(128).optional(),"C")}).strict()});var exports_session_id_written={};__export(exports_session_id_written,{schema:()=>schema35,TYPE:()=>TYPE34,SCHEMA_VERSION:()=>SCHEMA_VERSION34,KIND:()=>KIND34});var SCHEMA_VERSION34=1,TYPE34="session.id.written",KIND34="event",AgentIdSchema5,SessionIdSchema3,ExecutorSchema4,OriginSchema,DiffSchema2,schema35;var init_session_id_written=__esm(()=>{init_zod();init_redactors();AgentIdSchema5=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),SessionIdSchema3=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("session",v)),"A"),ExecutorSchema4=tagTier(exports_external.enum(["claude-code","claude-sdk","codex","shell"]),"C"),OriginSchema=tagTier(exports_external.enum(["spawn","resume","backfill","reconcile"]),"C"),DiffSchema2=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B","shallow scalar diff \u2014 session_id hashed before arriving here"),schema35=exports_external.object({agent_id:AgentIdSchema5,session_id:SessionIdSchema3,executor:ExecutorSchema4,origin:OriginSchema,before:DiffSchema2,after:DiffSchema2}).strict()});var exports_session_reconciled={};__export(exports_session_reconciled,{schema:()=>schema36,TYPE:()=>TYPE35,SCHEMA_VERSION:()=>SCHEMA_VERSION35,KIND:()=>KIND35});var SCHEMA_VERSION35=1,TYPE35="session.reconciled",KIND35="event",AgentIdSchema6,SessionIdSchema4,ReasonSchema6,DiffSchema3,schema36;var init_session_reconciled=__esm(()=>{init_zod();init_redactors();AgentIdSchema6=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),SessionIdSchema4=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("session",v)),"A"),ReasonSchema6=tagTier(exports_external.enum(["transcript-discovered","stale-pg-session","idle-timeout","manual","backfill"]),"C"),DiffSchema3=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B"),schema36=exports_external.object({agent_id:AgentIdSchema6,old_session_id:SessionIdSchema4.optional(),new_session_id:SessionIdSchema4,reason:ReasonSchema6,before:DiffSchema3,after:DiffSchema3}).strict()});var exports_state_transition={};__export(exports_state_transition,{schema:()=>schema37,TYPE:()=>TYPE36,SCHEMA_VERSION:()=>SCHEMA_VERSION36,KIND:()=>KIND36});var SCHEMA_VERSION36=1,TYPE36="state_transition",KIND36="event",EntityKindSchema,EntityIdSchema5,FromSchema2,ToSchema2,ReasonSchema7,ActorSchema3,DiffSchema4,schema37;var init_state_transition=__esm(()=>{init_zod();init_redactors();EntityKindSchema=tagTier(exports_external.enum(["task","wish","worker","team","team_lead","group","mailbox_message"]),"C"),EntityIdSchema5=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("entity",v)),"A","entity id hashed"),FromSchema2=tagTier(exports_external.string().min(1).max(64),"C"),ToSchema2=tagTier(exports_external.string().min(1).max(64),"C"),ReasonSchema7=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B","redacted free-text"),ActorSchema3=tagTier(exports_external.string().max(128).transform((v)=>redactFreeText(v)).optional(),"B"),DiffSchema4=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B","shallow scalar diff only"),schema37=exports_external.object({entity_kind:EntityKindSchema,entity_id:EntityIdSchema5,from:FromSchema2,to:ToSchema2,reason:ReasonSchema7,actor:ActorSchema3,before:DiffSchema4,after:DiffSchema4}).strict()});var exports_stream_gap_detected={};__export(exports_stream_gap_detected,{schema:()=>schema38,TYPE:()=>TYPE37,SCHEMA_VERSION:()=>SCHEMA_VERSION37,KIND:()=>KIND37});var SCHEMA_VERSION37=1,TYPE37="stream.gap.detected",KIND37="event",ConsumerIdSchema2,IdSchema,CountSchema6,schema38;var init_stream_gap_detected=__esm(()=>{init_zod();init_redactors();ConsumerIdSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("consumer",v)),"A"),IdSchema=tagTier(exports_external.number().int().min(0).max(Number.MAX_SAFE_INTEGER),"C"),CountSchema6=tagTier(exports_external.number().int().min(1).max(1e7),"C"),schema38=exports_external.object({consumer_id:ConsumerIdSchema2,from_id:IdSchema,to_id:IdSchema,missing_count:CountSchema6}).strict()});var exports_team_create={};__export(exports_team_create,{schema:()=>schema39,TYPE:()=>TYPE38,SCHEMA_VERSION:()=>SCHEMA_VERSION38,KIND:()=>KIND38,DEFAULT_TIER:()=>DEFAULT_TIER5});var SCHEMA_VERSION38=1,TYPE38="team.create",KIND38="event",DEFAULT_TIER5="audit",TeamNameSchema2,WishSlugSchema,RepoPathHashSchema,ActorSchema4,MemberCountSchema,AutoSchema,schema39;var init_team_create=__esm(()=>{init_zod();init_redactors();TeamNameSchema2=tagTier(exports_external.string().min(1).max(128),"C","team name \u2014 public label"),WishSlugSchema=tagTier(exports_external.string().max(128).optional(),"C"),RepoPathHashSchema=tagTier(exports_external.string().min(1).max(1024).transform((v)=>hashEntity("repo",v)),"A"),ActorSchema4=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("actor",v)),"A"),MemberCountSchema=tagTier(exports_external.number().int().min(0).max(256).optional(),"C"),AutoSchema=tagTier(exports_external.boolean().optional(),"C","true if created by auto-spawn hook"),schema39=exports_external.object({team_name:TeamNameSchema2,wish_slug:WishSlugSchema,repo_path_hash:RepoPathHashSchema,actor:ActorSchema4,member_count:MemberCountSchema,auto:AutoSchema}).strict()});var exports_team_disband={};__export(exports_team_disband,{schema:()=>schema40,TYPE:()=>TYPE39,SCHEMA_VERSION:()=>SCHEMA_VERSION39,KIND:()=>KIND39,DEFAULT_TIER:()=>DEFAULT_TIER6});var SCHEMA_VERSION39=1,TYPE39="team.disband",KIND39="event",DEFAULT_TIER6="audit",TeamNameSchema3,ActorSchema5,RemainingMembersSchema,ReasonSchema8,schema40;var init_team_disband=__esm(()=>{init_zod();init_redactors();TeamNameSchema3=tagTier(exports_external.string().min(1).max(128),"C"),ActorSchema5=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("actor",v)).optional(),"A"),RemainingMembersSchema=tagTier(exports_external.number().int().min(0).max(256).optional(),"C"),ReasonSchema8=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B"),schema40=exports_external.object({team_name:TeamNameSchema3,actor:ActorSchema5,remaining_members:RemainingMembersSchema,reason:ReasonSchema8}).strict()});var exports_tmux_pane_placed={};__export(exports_tmux_pane_placed,{schema:()=>schema41,TYPE:()=>TYPE40,SCHEMA_VERSION:()=>SCHEMA_VERSION40,KIND:()=>KIND40});var SCHEMA_VERSION40=1,TYPE40="tmux.pane.placed",KIND40="event",AgentIdSchema7,SessionSchema,WindowIndexSchema,PaneIndexSchema,PaneIdSchema,ActionSchema,schema41;var init_tmux_pane_placed=__esm(()=>{init_zod();init_redactors();AgentIdSchema7=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),SessionSchema=tagTier(exports_external.string().min(1).max(128),"C","tmux session name \u2014 public"),WindowIndexSchema=tagTier(exports_external.number().int().min(0).max(256),"C"),PaneIndexSchema=tagTier(exports_external.number().int().min(0).max(256),"C"),PaneIdSchema=tagTier(exports_external.string().max(64).optional(),"C","tmux pane id \u2014 public"),ActionSchema=tagTier(exports_external.enum(["spawn","attach","replace","split"]),"C"),schema41=exports_external.object({agent_id:AgentIdSchema7,session:SessionSchema,window_index:WindowIndexSchema,pane_index:PaneIndexSchema,pane_id:PaneIdSchema,action:ActionSchema}).strict()});var exports_wish_dispatch={};__export(exports_wish_dispatch,{schema:()=>schema42,TYPE:()=>TYPE41,SCHEMA_VERSION:()=>SCHEMA_VERSION41,KIND:()=>KIND41});var SCHEMA_VERSION41=1,TYPE41="wish.dispatch",KIND41="span",WishSlugSchema2,WaveSchema,GroupIdSchema,GroupNameSchema,ActorSchema6,OutcomeSchema3,DurationSchema7,DryRunSchema,schema42;var init_wish_dispatch=__esm(()=>{init_zod();init_redactors();WishSlugSchema2=tagTier(exports_external.string().min(1).max(128),"C","wish slug \u2014 public"),WaveSchema=tagTier(exports_external.number().int().min(0).max(32),"C"),GroupIdSchema=tagTier(exports_external.string().min(1).max(128).transform((v)=>hashEntity("group",v)),"A","group id hashed"),GroupNameSchema=tagTier(exports_external.string().max(128),"C"),ActorSchema6=tagTier(exports_external.string().max(128).transform((v)=>redactFreeText(v)).optional(),"B"),OutcomeSchema3=tagTier(exports_external.enum(["started","completed","failed","blocked"]).optional(),"C"),DurationSchema7=tagTier(exports_external.number().int().min(0).max(86400000).optional(),"C","ms"),DryRunSchema=tagTier(exports_external.boolean().optional(),"C"),schema42=exports_external.object({wish_slug:WishSlugSchema2,wave:WaveSchema.optional(),group_id:GroupIdSchema.optional(),group_name:GroupNameSchema.optional(),actor:ActorSchema6,outcome:OutcomeSchema3,duration_ms:DurationSchema7,dry_run:DryRunSchema}).strict()});function entry(mod){return{type:mod.TYPE,kind:mod.KIND,schema:mod.schema,schema_version:mod.SCHEMA_VERSION,tier_defaults:mod.DEFAULT_TIER??"default"}}function getEntry(type2){return EventRegistry[type2]??null}function isRegistered(type2){return Object.hasOwn(EventRegistry,type2)}var EventRegistry;var init_registry=__esm(()=>{init_agent_lifecycle();init_agent_resume_attempted();init_agent_resume_failed();init_agent_resume_succeeded();init_audit_export();init_audit_un_hash();init_cache_hit();init_cache_invalidate();init_cli_command();init_consumer_heartbeat();init_consumer_lagged();init_correlation_orphan_rate();init_detector_disabled();init_emit_backpressure_critical();init_emitter_latency_p99();init_emitter_queue_depth();init_emitter_rejected();init_emitter_shedding_load();init_error_raised();init_executor_row_written();init_executor_write();init_hook_delivery();init_mailbox_delivery();init_notify_delivery_lag();init_permissions_deny();init_permissions_grant();init_resume_attempt();init_rot_detected();init_rot_executor_ghost_detected();init_rot_inbox_watcher_spawn_loop_detected();init_rot_team_ls_drift_detected();init_runbook_triggered();init_schema_violation();init_session_id_written();init_session_reconciled();init_state_transition();init_stream_gap_detected();init_team_create();init_team_disband();init_tmux_pane_placed();init_wish_dispatch();EventRegistry={[TYPE9]:entry(exports_cli_command),[TYPE]:entry(exports_agent_lifecycle),[TYPE41]:entry(exports_wish_dispatch),[TYPE22]:entry(exports_hook_delivery),[TYPE27]:entry(exports_resume_attempt),[TYPE21]:entry(exports_executor_write),[TYPE23]:entry(exports_mailbox_delivery),[TYPE19]:entry(exports_error_raised),[TYPE36]:entry(exports_state_transition),[TYPE33]:entry(exports_schema_violation),[TYPE34]:entry(exports_session_id_written),[TYPE35]:entry(exports_session_reconciled),[TYPE40]:entry(exports_tmux_pane_placed),[TYPE20]:entry(exports_executor_row_written),[TYPE8]:entry(exports_cache_invalidate),[TYPE7]:entry(exports_cache_hit),[TYPE32]:entry(exports_runbook_triggered),[TYPE10]:entry(exports_consumer_heartbeat),[TYPE26]:entry(exports_permissions_grant),[TYPE25]:entry(exports_permissions_deny),[TYPE38]:entry(exports_team_create),[TYPE39]:entry(exports_team_disband),[TYPE6]:entry(exports_audit_un_hash),[TYPE5]:entry(exports_audit_export),[TYPE17]:entry(exports_emitter_rejected),[TYPE16]:entry(exports_emitter_queue_depth),[TYPE15]:entry(exports_emitter_latency_p99),[TYPE24]:entry(exports_notify_delivery_lag),[TYPE37]:entry(exports_stream_gap_detected),[TYPE12]:entry(exports_correlation_orphan_rate),[TYPE18]:entry(exports_emitter_shedding_load),[TYPE11]:entry(exports_consumer_lagged),[TYPE14]:entry(exports_emit_backpressure_critical),[TYPE13]:entry(exports_detector_disabled),[TYPE28]:entry(exports_rot_detected),[TYPE31]:entry(exports_rot_team_ls_drift_detected),[TYPE29]:entry(exports_rot_executor_ghost_detected),[TYPE30]:entry(exports_rot_inbox_watcher_spawn_loop_detected),[TYPE2]:entry(exports_agent_resume_attempted),[TYPE4]:entry(exports_agent_resume_succeeded),[TYPE3]:entry(exports_agent_resume_failed)}});var exports_emit={};__export(exports_emit,{startSpan:()=>startSpan,shutdownEmitter:()=>shutdownEmitter,resumeEmitter:()=>resumeEmitter,isSpillJournalEmpty:()=>isSpillJournalEmpty,getEmitStats:()=>getEmitStats,flushNow:()=>flushNow,endSpan:()=>endSpan,emitEvent:()=>emitEvent,drainSpillJournalNow:()=>drainSpillJournalNow,__setSpillPathForTests:()=>__setSpillPathForTests,__resetEmitForTests:()=>__resetEmitForTests,__TEST_QUEUE_CAP:()=>__TEST_QUEUE_CAP,__TEST_BACKPRESSURE_WAIT_MS:()=>__TEST_BACKPRESSURE_WAIT_MS});import{createHash as createHash2,randomUUID as randomUUID3}from"crypto";import{appendFileSync,closeSync,existsSync as existsSync14,fsyncSync,mkdirSync as mkdirSync7,openSync,readFileSync as readFileSync10,renameSync as renameSync2,statSync as statSync2,unlinkSync as unlinkSync4}from"fs";import{homedir as homedir13}from"os";import{dirname as dirname5,join as join18}from"path";function getEmitStats(){return{...stats,queue_depth:queue.length}}function defaultSpillPath(){let home=process.env.GENIE_HOME??join18(homedir13(),".genie");return join18(home,"data","emit-spill.jsonl")}function __setSpillPathForTests(path2){spillPathOverride=path2}function spillPath(){return spillPathOverride??defaultSpillPath()}function ensureSpillDir(path2){let dir=dirname5(path2);if(!existsSync14(dir))mkdirSync7(dir,{recursive:!0})}function writeSpillRow(row){let path2=spillPath();ensureSpillDir(path2);let line=`${JSON.stringify(row)}
|
|
687
|
+
`)),"B","stack paths tokenized"),SubsystemSchema=tagTier(exports_external.string().min(1).max(128),"C"),SeveritySchema2=tagTier(exports_external.enum(["warn","error","fatal"]),"C"),RetryableSchema=tagTier(exports_external.boolean().optional(),"C"),schema20=exports_external.object({error_class:ErrorClassSchema,message:MessageSchema,stack:StackSchema.optional(),subsystem:SubsystemSchema,severity:SeveritySchema2,retryable:RetryableSchema}).strict()});var exports_executor_row_written={};__export(exports_executor_row_written,{schema:()=>schema21,TYPE:()=>TYPE20,SCHEMA_VERSION:()=>SCHEMA_VERSION20,KIND:()=>KIND20});var SCHEMA_VERSION20=1,TYPE20="executor.row.written",KIND20="event",TableSchema,RowIdSchema,OperationSchema,ExecutorSchema2,DiffSchema,schema21;var init_executor_row_written=__esm(()=>{init_zod();init_redactors();TableSchema=tagTier(exports_external.string().min(1).max(128),"C","PG table name \u2014 public"),RowIdSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("row",v)),"A"),OperationSchema=tagTier(exports_external.enum(["insert","update","delete","upsert"]),"C"),ExecutorSchema2=tagTier(exports_external.string().max(128).optional(),"C"),DiffSchema=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B","shallow scalar diff only \u2014 payloads never stored here"),schema21=exports_external.object({table:TableSchema,row_id:RowIdSchema,operation:OperationSchema,executor:ExecutorSchema2,before:DiffSchema,after:DiffSchema}).strict()});var exports_executor_write={};__export(exports_executor_write,{schema:()=>schema22,TYPE:()=>TYPE21,SCHEMA_VERSION:()=>SCHEMA_VERSION21,KIND:()=>KIND21});var SCHEMA_VERSION21=1,TYPE21="executor.write",KIND21="span",ExecutorSchema3,TargetSchema,TableSchema2,OperationSchema2,RowsAffectedSchema,DurationSchema3,OutcomeSchema,ErrorHintSchema,schema22;var init_executor_write=__esm(()=>{init_zod();init_redactors();ExecutorSchema3=tagTier(exports_external.enum(["claude-code","claude-sdk","codex","shell"]),"C"),TargetSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("executor_target",v)),"A","target entity hashed"),TableSchema2=tagTier(exports_external.string().max(128).optional(),"C","PG table name \u2014 public"),OperationSchema2=tagTier(exports_external.enum(["insert","update","delete","upsert","copy","truncate"]),"C"),RowsAffectedSchema=tagTier(exports_external.number().int().min(0).max(1e7).optional(),"C"),DurationSchema3=tagTier(exports_external.number().int().min(0).max(60000).optional(),"C","ms"),OutcomeSchema=tagTier(exports_external.enum(["ok","constraint_violation","timeout","error"]).optional(),"C"),ErrorHintSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B"),schema22=exports_external.object({executor:ExecutorSchema3,target:TargetSchema,table:TableSchema2,operation:OperationSchema2,rows_affected:RowsAffectedSchema,duration_ms:DurationSchema3,outcome:OutcomeSchema,error_hint:ErrorHintSchema}).strict()});var exports_hook_delivery={};__export(exports_hook_delivery,{schema:()=>schema23,TYPE:()=>TYPE22,SCHEMA_VERSION:()=>SCHEMA_VERSION22,KIND:()=>KIND22});var SCHEMA_VERSION22=1,TYPE22="hook.delivery",KIND22="span",HookNameSchema,HookEventSchema,AgentIdSchema2,ToolSchema,StatusSchema,DurationSchema4,ExitCodeSchema2,StderrExcerptSchema,schema23;var init_hook_delivery=__esm(()=>{init_zod();init_redactors();HookNameSchema=tagTier(exports_external.string().min(1).max(128),"C","hook name \u2014 public"),HookEventSchema=tagTier(exports_external.string().min(1).max(64),"C","CC hook event name \u2014 public"),AgentIdSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),ToolSchema=tagTier(exports_external.string().max(128).optional(),"C"),StatusSchema=tagTier(exports_external.enum(["ok","timeout","rejected","error"]).optional(),"C"),DurationSchema4=tagTier(exports_external.number().int().min(0).max(60000).optional(),"C","ms (<=15s timeout)"),ExitCodeSchema2=tagTier(exports_external.number().int().min(-1).max(255).optional(),"C"),StderrExcerptSchema=tagTier(exports_external.string().max(4096).transform((v)=>redactFreeText(v)).optional(),"B","redacted stderr excerpt"),schema23=exports_external.object({hook_name:HookNameSchema,agent_id:AgentIdSchema2,tool:ToolSchema,event:HookEventSchema.optional(),status:StatusSchema,duration_ms:DurationSchema4,exit_code:ExitCodeSchema2,stderr_excerpt:StderrExcerptSchema}).strict()});var exports_mailbox_delivery={};__export(exports_mailbox_delivery,{schema:()=>schema24,TYPE:()=>TYPE23,SCHEMA_VERSION:()=>SCHEMA_VERSION23,KIND:()=>KIND23});var SCHEMA_VERSION23=1,TYPE23="mailbox.delivery",KIND23="span",AgentIdSchema3=(ns)=>tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity(ns,v)),"A"),FromSchema,ToSchema,ChannelSchema,OutcomeSchema2,MessageIdSchema,BodyExcerptSchema,DurationSchema5,schema24;var init_mailbox_delivery=__esm(()=>{init_zod();init_redactors();FromSchema=tagTier(exports_external.string().max(128),"C","sender role \u2014 public"),ToSchema=tagTier(exports_external.string().max(128),"C","recipient role \u2014 public"),ChannelSchema=tagTier(exports_external.enum(["tmux","native-inbox","file","broadcast"]),"C"),OutcomeSchema2=tagTier(exports_external.enum(["delivered","queued","pane_dead","rejected","timeout"]).optional(),"C"),MessageIdSchema=AgentIdSchema3("msg").optional(),BodyExcerptSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B","first 512 chars, redacted"),DurationSchema5=tagTier(exports_external.number().int().min(0).max(60000).optional(),"C","ms"),schema24=exports_external.object({from:FromSchema,to:ToSchema,channel:ChannelSchema,outcome:OutcomeSchema2,message_id:MessageIdSchema,body_excerpt:BodyExcerptSchema,duration_ms:DurationSchema5}).strict()});var exports_notify_delivery_lag={};__export(exports_notify_delivery_lag,{schema:()=>schema25,TYPE:()=>TYPE24,SCHEMA_VERSION:()=>SCHEMA_VERSION24,KIND:()=>KIND24});var SCHEMA_VERSION24=1,TYPE24="notify.delivery.lag",KIND24="event",NonceSchema,LagMillisSchema,ChannelSchema2,schema25;var init_notify_delivery_lag=__esm(()=>{init_zod();init_redactors();NonceSchema=tagTier(exports_external.string().min(1).max(128).transform((v)=>hashEntity("notify-probe",v)),"A"),LagMillisSchema=tagTier(exports_external.number().min(0).max(300000),"C"),ChannelSchema2=tagTier(exports_external.string().min(1).max(128),"C"),schema25=exports_external.object({channel:ChannelSchema2,probe_id:NonceSchema,lag_ms:LagMillisSchema,timed_out:tagTier(exports_external.boolean(),"C")}).strict()});var exports_permissions_deny={};__export(exports_permissions_deny,{schema:()=>schema26,TYPE:()=>TYPE25,SCHEMA_VERSION:()=>SCHEMA_VERSION25,KIND:()=>KIND25});var SCHEMA_VERSION25=1,TYPE25="permissions.deny",KIND25="event",ActorSchema,AttemptedRoleSchema,ScopeSchema2,ReasonSchema5,SourceIpSchema,schema26;var init_permissions_deny=__esm(()=>{init_zod();init_redactors();ActorSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A"),AttemptedRoleSchema=tagTier(exports_external.string().min(1).max(64),"C"),ScopeSchema2=tagTier(exports_external.string().min(1).max(128),"C"),ReasonSchema5=tagTier(exports_external.enum(["token_expired","token_invalid","signature_invalid","scope_mismatch","tenant_mismatch","rate_limited","revoked","unknown"]),"C"),SourceIpSchema=tagTier(exports_external.string().max(64).transform((v)=>hashEntity("ip",v)).optional(),"A"),schema26=exports_external.object({actor:ActorSchema,attempted_role:AttemptedRoleSchema,scope:ScopeSchema2,reason:ReasonSchema5,source_ip:SourceIpSchema}).strict()});var exports_permissions_grant={};__export(exports_permissions_grant,{schema:()=>schema27,TYPE:()=>TYPE26,SCHEMA_VERSION:()=>SCHEMA_VERSION26,KIND:()=>KIND26});var SCHEMA_VERSION26=1,TYPE26="permissions.grant",KIND26="event",ActorSchema2,RoleSchema2,ScopeSchema3,ExpiresAtSchema,GrantedBySchema,schema27;var init_permissions_grant=__esm(()=>{init_zod();init_redactors();ActorSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("actor",v)),"A"),RoleSchema2=tagTier(exports_external.enum(["admin","operator","subscriber","audit"]),"C"),ScopeSchema3=tagTier(exports_external.string().min(1).max(128),"C",'e.g. "genie_events.agent.*" \u2014 public'),ExpiresAtSchema=tagTier(exports_external.string().datetime().optional(),"C"),GrantedBySchema=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("actor",v)).optional(),"A"),schema27=exports_external.object({actor:ActorSchema2,role:RoleSchema2,scope:ScopeSchema3,expires_at:ExpiresAtSchema,granted_by:GrantedBySchema}).strict()});var exports_resume_attempt={};__export(exports_resume_attempt,{schema:()=>schema28,TYPE:()=>TYPE27,SCHEMA_VERSION:()=>SCHEMA_VERSION27,KIND:()=>KIND27});var SCHEMA_VERSION27=1,TYPE27="resume.attempt",KIND27="span",AgentIdSchema4,AttemptNumberSchema4,StrategySchema,SessionIdSchema2,SucceededSchema,FailureReasonSchema,DurationSchema6,schema28;var init_resume_attempt=__esm(()=>{init_zod();init_redactors();AgentIdSchema4=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),AttemptNumberSchema4=tagTier(exports_external.number().int().min(1).max(16),"C"),StrategySchema=tagTier(exports_external.enum(["tmux-attach","claude-resume-session","cold-start","session-backfill"]),"C"),SessionIdSchema2=tagTier(exports_external.string().max(128).transform((v)=>hashEntity("session",v)).optional(),"A"),SucceededSchema=tagTier(exports_external.boolean().optional(),"C"),FailureReasonSchema=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B"),DurationSchema6=tagTier(exports_external.number().int().min(0).max(300000).optional(),"C","ms"),schema28=exports_external.object({agent_id:AgentIdSchema4,attempt_number:AttemptNumberSchema4,strategy:StrategySchema,session_id:SessionIdSchema2,succeeded:SucceededSchema,failure_reason:FailureReasonSchema,duration_ms:DurationSchema6}).strict()});var exports_rot_detected={};__export(exports_rot_detected,{schema:()=>schema29,TYPE:()=>TYPE28,SCHEMA_VERSION:()=>SCHEMA_VERSION28,KIND:()=>KIND28});var SCHEMA_VERSION28=1,TYPE28="rot.detected",KIND28="event",PatternIdSchema,EntityIdSchema4,ObservedValueSchema,ObservedStateSchema,schema29;var init_rot_detected=__esm(()=>{init_zod();init_redactors();PatternIdSchema=tagTier(exports_external.string().min(1).max(128).regex(/^[a-z0-9][a-z0-9._-]*$/,"pattern_id must be kebab/dot/underscore lowercase"),"C"),EntityIdSchema4=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("entity",v)),"A"),ObservedValueSchema=tagTier(exports_external.union([exports_external.string().max(4096).transform(redactFreeText),exports_external.number().finite(),exports_external.boolean(),exports_external.null(),exports_external.array(exports_external.string().max(1024).transform(redactFreeText)).max(256),exports_external.array(exports_external.number().finite()).max(256)]),"B","evidence scalar \u2014 free text runs through redactFreeText"),ObservedStateSchema=tagTier(exports_external.record(exports_external.string().min(1).max(64).regex(/^[a-z0-9_]+$/,"observed_state key must be snake_case"),ObservedValueSchema).refine((obj)=>Object.keys(obj).length<=32,{message:"observed_state_json cannot exceed 32 keys"}),"B","per-pattern evidence record \u2014 keys documented by each detector module"),schema29=exports_external.object({pattern_id:PatternIdSchema,entity_id:EntityIdSchema4,observed_state_json:ObservedStateSchema}).strict()});var exports_rot_executor_ghost_detected={};__export(exports_rot_executor_ghost_detected,{schema:()=>schema30,TYPE:()=>TYPE29,SCHEMA_VERSION:()=>SCHEMA_VERSION29,KIND:()=>KIND29});var SCHEMA_VERSION29=1,TYPE29="rot.executor-ghost.detected",KIND29="event",ResolutionSourceSchema,EnvIdSchema,ResolvedIdSchema,AgentNameSchema,RecoveredSchema,schema30;var init_rot_executor_ghost_detected=__esm(()=>{init_zod();ResolutionSourceSchema=tagTier(exports_external.enum(["resolver","reconciler"]),"C"),EnvIdSchema=tagTier(exports_external.string().uuid(),"C"),ResolvedIdSchema=tagTier(exports_external.string().uuid(),"C"),AgentNameSchema=tagTier(exports_external.string().min(1).max(256),"C"),RecoveredSchema=tagTier(exports_external.boolean(),"C"),schema30=exports_external.object({resolution_source:ResolutionSourceSchema,env_id:EnvIdSchema,resolved_id:ResolvedIdSchema,agent_name:AgentNameSchema,recovered:RecoveredSchema}).strict()});var exports_rot_inbox_watcher_spawn_loop_detected={};__export(exports_rot_inbox_watcher_spawn_loop_detected,{schema:()=>schema31,TYPE:()=>TYPE30,SCHEMA_VERSION:()=>SCHEMA_VERSION30,KIND:()=>KIND30});var SCHEMA_VERSION30=1,TYPE30="rot.inbox-watcher-spawn-loop.detected",KIND30="event",TeamNameSchema,SessionKeySchema,FailureCountSchema,LastErrorMessageSchema,schema31;var init_rot_inbox_watcher_spawn_loop_detected=__esm(()=>{init_zod();init_redactors();TeamNameSchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>redactFreeText(v)),"C"),SessionKeySchema=tagTier(exports_external.string().min(1).max(256).transform((v)=>redactFreeText(v)),"C"),FailureCountSchema=tagTier(exports_external.number().int().min(1).max(100),"C"),LastErrorMessageSchema=tagTier(exports_external.string().min(1).max(2048).transform((v)=>redactFreeText(v)),"B","redacted error message from the final failed ensureTeamLead() call"),schema31=exports_external.object({team_name:TeamNameSchema,session_key:SessionKeySchema,failure_count:FailureCountSchema,last_error_message:LastErrorMessageSchema}).strict()});var exports_rot_team_ls_drift_detected={};__export(exports_rot_team_ls_drift_detected,{schema:()=>schema32,TYPE:()=>TYPE31,SCHEMA_VERSION:()=>SCHEMA_VERSION31,KIND:()=>KIND31});var SCHEMA_VERSION31=1,TYPE31="rot.team-ls-drift.detected",KIND31="event",DivergenceKindSchema,DivergentCountSchema,ObservedStateJsonSchema,ObservedStateJsonTruncatedSchema,schema32;var init_rot_team_ls_drift_detected=__esm(()=>{init_zod();init_redactors();DivergenceKindSchema=tagTier(exports_external.enum(["missing_in_disband","missing_in_ls","status_mismatch"]),"C"),DivergentCountSchema=tagTier(exports_external.number().int().min(1).max(1e4),"C"),ObservedStateJsonSchema=tagTier(exports_external.string().min(2).max(16384).transform((v)=>redactFreeText(v)),"B","JSON-encoded snapshot of both data sources for triage"),ObservedStateJsonTruncatedSchema=tagTier(exports_external.literal(!0).optional(),"C","set when detail was dropped to honor the observed_state_json cap"),schema32=exports_external.object({divergence_kind:DivergenceKindSchema,divergent_count:DivergentCountSchema,observed_state_json:ObservedStateJsonSchema,observed_state_json_truncated:ObservedStateJsonTruncatedSchema}).strict()});var exports_runbook_triggered={};__export(exports_runbook_triggered,{schema:()=>schema33,TYPE:()=>TYPE32,SCHEMA_VERSION:()=>SCHEMA_VERSION32,KIND:()=>KIND32});var SCHEMA_VERSION32=1,TYPE32="runbook.triggered",KIND32="event",RuleSchema,EvidenceCountSchema,CorrelationIdSchema,WindowMinutesSchema,RecommendedSqlSchema,EvidenceSummarySchema,schema33;var init_runbook_triggered=__esm(()=>{init_zod();init_redactors();RuleSchema=tagTier(exports_external.string().min(1).max(64).regex(/^R\d+$/,"rule id must be R<int>"),"C"),EvidenceCountSchema=tagTier(exports_external.number().int().min(1).max(1e6),"C"),CorrelationIdSchema=tagTier(exports_external.string().max(128).transform((v)=>hashEntity("trace",v)).optional(),"A"),WindowMinutesSchema=tagTier(exports_external.number().int().min(1).max(1440).optional(),"C"),RecommendedSqlSchema=tagTier(exports_external.string().max(4096).transform((v)=>redactFreeText(v)).optional(),"B","mitigation SQL \u2014 redacted free text"),EvidenceSummarySchema=tagTier(exports_external.string().max(1024).transform((v)=>redactFreeText(v)).optional(),"B"),schema33=exports_external.object({rule:RuleSchema,evidence_count:EvidenceCountSchema,window_minutes:WindowMinutesSchema,correlation_id:CorrelationIdSchema,recommended_sql:RecommendedSqlSchema,evidence_summary:EvidenceSummarySchema}).strict()});var exports_schema_violation={};__export(exports_schema_violation,{schema:()=>schema34,TYPE:()=>TYPE33,SCHEMA_VERSION:()=>SCHEMA_VERSION33,KIND:()=>KIND33});var SCHEMA_VERSION33=1,TYPE33="schema.violation",KIND33="event",OffendingTypeSchema2,RejectedBytesSchema,IssueSchema,schema34;var init_schema_violation=__esm(()=>{init_zod();init_redactors();OffendingTypeSchema2=tagTier(exports_external.string().min(1).max(128),"C"),RejectedBytesSchema=tagTier(exports_external.number().int().min(0).max(1048576),"C"),IssueSchema=tagTier(exports_external.object({path:exports_external.string().max(256),code:exports_external.string().max(64),message:exports_external.string().max(512).transform(redactFreeText)}),"B"),schema34=exports_external.object({offending_type:OffendingTypeSchema2,issues:tagTier(exports_external.array(IssueSchema).max(32),"B"),rejected_bytes:RejectedBytesSchema,source_subsystem:tagTier(exports_external.string().max(128).optional(),"C")}).strict()});var exports_session_id_written={};__export(exports_session_id_written,{schema:()=>schema35,TYPE:()=>TYPE34,SCHEMA_VERSION:()=>SCHEMA_VERSION34,KIND:()=>KIND34});var SCHEMA_VERSION34=1,TYPE34="session.id.written",KIND34="event",AgentIdSchema5,SessionIdSchema3,ExecutorSchema4,OriginSchema,DiffSchema2,schema35;var init_session_id_written=__esm(()=>{init_zod();init_redactors();AgentIdSchema5=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),SessionIdSchema3=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("session",v)),"A"),ExecutorSchema4=tagTier(exports_external.enum(["claude-code","claude-sdk","codex","shell"]),"C"),OriginSchema=tagTier(exports_external.enum(["spawn","resume","backfill","reconcile"]),"C"),DiffSchema2=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B","shallow scalar diff \u2014 session_id hashed before arriving here"),schema35=exports_external.object({agent_id:AgentIdSchema5,session_id:SessionIdSchema3,executor:ExecutorSchema4,origin:OriginSchema,before:DiffSchema2,after:DiffSchema2}).strict()});var exports_session_reconciled={};__export(exports_session_reconciled,{schema:()=>schema36,TYPE:()=>TYPE35,SCHEMA_VERSION:()=>SCHEMA_VERSION35,KIND:()=>KIND35});var SCHEMA_VERSION35=1,TYPE35="session.reconciled",KIND35="event",AgentIdSchema6,SessionIdSchema4,ReasonSchema6,DiffSchema3,schema36;var init_session_reconciled=__esm(()=>{init_zod();init_redactors();AgentIdSchema6=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),SessionIdSchema4=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("session",v)),"A"),ReasonSchema6=tagTier(exports_external.enum(["transcript-discovered","stale-pg-session","idle-timeout","manual","backfill"]),"C"),DiffSchema3=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B"),schema36=exports_external.object({agent_id:AgentIdSchema6,old_session_id:SessionIdSchema4.optional(),new_session_id:SessionIdSchema4,reason:ReasonSchema6,before:DiffSchema3,after:DiffSchema3}).strict()});var exports_state_transition={};__export(exports_state_transition,{schema:()=>schema37,TYPE:()=>TYPE36,SCHEMA_VERSION:()=>SCHEMA_VERSION36,KIND:()=>KIND36});var SCHEMA_VERSION36=1,TYPE36="state_transition",KIND36="event",EntityKindSchema,EntityIdSchema5,FromSchema2,ToSchema2,ReasonSchema7,ActorSchema3,DiffSchema4,schema37;var init_state_transition=__esm(()=>{init_zod();init_redactors();EntityKindSchema=tagTier(exports_external.enum(["task","wish","worker","team","team_lead","group","mailbox_message"]),"C"),EntityIdSchema5=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("entity",v)),"A","entity id hashed"),FromSchema2=tagTier(exports_external.string().min(1).max(64),"C"),ToSchema2=tagTier(exports_external.string().min(1).max(64),"C"),ReasonSchema7=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B","redacted free-text"),ActorSchema3=tagTier(exports_external.string().max(128).transform((v)=>redactFreeText(v)).optional(),"B"),DiffSchema4=tagTier(exports_external.record(exports_external.string(),exports_external.union([exports_external.string(),exports_external.number(),exports_external.boolean(),exports_external.null()])).default({}),"B","shallow scalar diff only"),schema37=exports_external.object({entity_kind:EntityKindSchema,entity_id:EntityIdSchema5,from:FromSchema2,to:ToSchema2,reason:ReasonSchema7,actor:ActorSchema3,before:DiffSchema4,after:DiffSchema4}).strict()});var exports_stream_gap_detected={};__export(exports_stream_gap_detected,{schema:()=>schema38,TYPE:()=>TYPE37,SCHEMA_VERSION:()=>SCHEMA_VERSION37,KIND:()=>KIND37});var SCHEMA_VERSION37=1,TYPE37="stream.gap.detected",KIND37="event",ConsumerIdSchema2,IdSchema,CountSchema6,schema38;var init_stream_gap_detected=__esm(()=>{init_zod();init_redactors();ConsumerIdSchema2=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("consumer",v)),"A"),IdSchema=tagTier(exports_external.number().int().min(0).max(Number.MAX_SAFE_INTEGER),"C"),CountSchema6=tagTier(exports_external.number().int().min(1).max(1e7),"C"),schema38=exports_external.object({consumer_id:ConsumerIdSchema2,from_id:IdSchema,to_id:IdSchema,missing_count:CountSchema6}).strict()});var exports_team_create={};__export(exports_team_create,{schema:()=>schema39,TYPE:()=>TYPE38,SCHEMA_VERSION:()=>SCHEMA_VERSION38,KIND:()=>KIND38,DEFAULT_TIER:()=>DEFAULT_TIER5});var SCHEMA_VERSION38=1,TYPE38="team.create",KIND38="event",DEFAULT_TIER5="audit",TeamNameSchema2,WishSlugSchema,RepoPathHashSchema,ActorSchema4,MemberCountSchema,AutoSchema,schema39;var init_team_create=__esm(()=>{init_zod();init_redactors();TeamNameSchema2=tagTier(exports_external.string().min(1).max(128),"C","team name \u2014 public label"),WishSlugSchema=tagTier(exports_external.string().max(128).optional(),"C"),RepoPathHashSchema=tagTier(exports_external.string().min(1).max(1024).transform((v)=>hashEntity("repo",v)),"A"),ActorSchema4=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("actor",v)),"A"),MemberCountSchema=tagTier(exports_external.number().int().min(0).max(256).optional(),"C"),AutoSchema=tagTier(exports_external.boolean().optional(),"C","true if created by auto-spawn hook"),schema39=exports_external.object({team_name:TeamNameSchema2,wish_slug:WishSlugSchema,repo_path_hash:RepoPathHashSchema,actor:ActorSchema4,member_count:MemberCountSchema,auto:AutoSchema}).strict()});var exports_team_disband={};__export(exports_team_disband,{schema:()=>schema40,TYPE:()=>TYPE39,SCHEMA_VERSION:()=>SCHEMA_VERSION39,KIND:()=>KIND39,DEFAULT_TIER:()=>DEFAULT_TIER6});var SCHEMA_VERSION39=1,TYPE39="team.disband",KIND39="event",DEFAULT_TIER6="audit",TeamNameSchema3,ActorSchema5,RemainingMembersSchema,ReasonSchema8,schema40;var init_team_disband=__esm(()=>{init_zod();init_redactors();TeamNameSchema3=tagTier(exports_external.string().min(1).max(128),"C"),ActorSchema5=tagTier(exports_external.string().max(256).transform((v)=>hashEntity("actor",v)).optional(),"A"),RemainingMembersSchema=tagTier(exports_external.number().int().min(0).max(256).optional(),"C"),ReasonSchema8=tagTier(exports_external.string().max(512).transform((v)=>redactFreeText(v)).optional(),"B"),schema40=exports_external.object({team_name:TeamNameSchema3,actor:ActorSchema5,remaining_members:RemainingMembersSchema,reason:ReasonSchema8}).strict()});var exports_tmux_pane_placed={};__export(exports_tmux_pane_placed,{schema:()=>schema41,TYPE:()=>TYPE40,SCHEMA_VERSION:()=>SCHEMA_VERSION40,KIND:()=>KIND40});var SCHEMA_VERSION40=1,TYPE40="tmux.pane.placed",KIND40="event",AgentIdSchema7,SessionSchema,WindowIndexSchema,PaneIndexSchema,PaneIdSchema,ActionSchema,schema41;var init_tmux_pane_placed=__esm(()=>{init_zod();init_redactors();AgentIdSchema7=tagTier(exports_external.string().min(1).max(256).transform((v)=>hashEntity("agent",v)),"A"),SessionSchema=tagTier(exports_external.string().min(1).max(128),"C","tmux session name \u2014 public"),WindowIndexSchema=tagTier(exports_external.number().int().min(0).max(256),"C"),PaneIndexSchema=tagTier(exports_external.number().int().min(0).max(256),"C"),PaneIdSchema=tagTier(exports_external.string().max(64).optional(),"C","tmux pane id \u2014 public"),ActionSchema=tagTier(exports_external.enum(["spawn","attach","replace","split"]),"C"),schema41=exports_external.object({agent_id:AgentIdSchema7,session:SessionSchema,window_index:WindowIndexSchema,pane_index:PaneIndexSchema,pane_id:PaneIdSchema,action:ActionSchema}).strict()});var exports_wish_dispatch={};__export(exports_wish_dispatch,{schema:()=>schema42,TYPE:()=>TYPE41,SCHEMA_VERSION:()=>SCHEMA_VERSION41,KIND:()=>KIND41});var SCHEMA_VERSION41=1,TYPE41="wish.dispatch",KIND41="span",WishSlugSchema2,WaveSchema,GroupIdSchema,GroupNameSchema,ActorSchema6,OutcomeSchema3,DurationSchema7,DryRunSchema,schema42;var init_wish_dispatch=__esm(()=>{init_zod();init_redactors();WishSlugSchema2=tagTier(exports_external.string().min(1).max(128),"C","wish slug \u2014 public"),WaveSchema=tagTier(exports_external.number().int().min(0).max(32),"C"),GroupIdSchema=tagTier(exports_external.string().min(1).max(128).transform((v)=>hashEntity("group",v)),"A","group id hashed"),GroupNameSchema=tagTier(exports_external.string().max(128),"C"),ActorSchema6=tagTier(exports_external.string().max(128).transform((v)=>redactFreeText(v)).optional(),"B"),OutcomeSchema3=tagTier(exports_external.enum(["started","completed","failed","blocked"]).optional(),"C"),DurationSchema7=tagTier(exports_external.number().int().min(0).max(86400000).optional(),"C","ms"),DryRunSchema=tagTier(exports_external.boolean().optional(),"C"),schema42=exports_external.object({wish_slug:WishSlugSchema2,wave:WaveSchema.optional(),group_id:GroupIdSchema.optional(),group_name:GroupNameSchema.optional(),actor:ActorSchema6,outcome:OutcomeSchema3,duration_ms:DurationSchema7,dry_run:DryRunSchema}).strict()});function entry(mod){return{type:mod.TYPE,kind:mod.KIND,schema:mod.schema,schema_version:mod.SCHEMA_VERSION,tier_defaults:mod.DEFAULT_TIER??"default"}}function getEntry(type2){return EventRegistry[type2]??null}function isRegistered(type2){return Object.hasOwn(EventRegistry,type2)}var EventRegistry;var init_registry=__esm(()=>{init_agent_lifecycle();init_agent_resume_attempted();init_agent_resume_failed();init_agent_resume_succeeded();init_audit_export();init_audit_un_hash();init_cache_hit();init_cache_invalidate();init_cli_command();init_consumer_heartbeat();init_consumer_lagged();init_correlation_orphan_rate();init_detector_disabled();init_emit_backpressure_critical();init_emitter_latency_p99();init_emitter_queue_depth();init_emitter_rejected();init_emitter_shedding_load();init_error_raised();init_executor_row_written();init_executor_write();init_hook_delivery();init_mailbox_delivery();init_notify_delivery_lag();init_permissions_deny();init_permissions_grant();init_resume_attempt();init_rot_detected();init_rot_executor_ghost_detected();init_rot_inbox_watcher_spawn_loop_detected();init_rot_team_ls_drift_detected();init_runbook_triggered();init_schema_violation();init_session_id_written();init_session_reconciled();init_state_transition();init_stream_gap_detected();init_team_create();init_team_disband();init_tmux_pane_placed();init_wish_dispatch();EventRegistry={[TYPE9]:entry(exports_cli_command),[TYPE]:entry(exports_agent_lifecycle),[TYPE41]:entry(exports_wish_dispatch),[TYPE22]:entry(exports_hook_delivery),[TYPE27]:entry(exports_resume_attempt),[TYPE21]:entry(exports_executor_write),[TYPE23]:entry(exports_mailbox_delivery),[TYPE19]:entry(exports_error_raised),[TYPE36]:entry(exports_state_transition),[TYPE33]:entry(exports_schema_violation),[TYPE34]:entry(exports_session_id_written),[TYPE35]:entry(exports_session_reconciled),[TYPE40]:entry(exports_tmux_pane_placed),[TYPE20]:entry(exports_executor_row_written),[TYPE8]:entry(exports_cache_invalidate),[TYPE7]:entry(exports_cache_hit),[TYPE32]:entry(exports_runbook_triggered),[TYPE10]:entry(exports_consumer_heartbeat),[TYPE26]:entry(exports_permissions_grant),[TYPE25]:entry(exports_permissions_deny),[TYPE38]:entry(exports_team_create),[TYPE39]:entry(exports_team_disband),[TYPE6]:entry(exports_audit_un_hash),[TYPE5]:entry(exports_audit_export),[TYPE17]:entry(exports_emitter_rejected),[TYPE16]:entry(exports_emitter_queue_depth),[TYPE15]:entry(exports_emitter_latency_p99),[TYPE24]:entry(exports_notify_delivery_lag),[TYPE37]:entry(exports_stream_gap_detected),[TYPE12]:entry(exports_correlation_orphan_rate),[TYPE18]:entry(exports_emitter_shedding_load),[TYPE11]:entry(exports_consumer_lagged),[TYPE14]:entry(exports_emit_backpressure_critical),[TYPE13]:entry(exports_detector_disabled),[TYPE28]:entry(exports_rot_detected),[TYPE31]:entry(exports_rot_team_ls_drift_detected),[TYPE29]:entry(exports_rot_executor_ghost_detected),[TYPE30]:entry(exports_rot_inbox_watcher_spawn_loop_detected),[TYPE2]:entry(exports_agent_resume_attempted),[TYPE4]:entry(exports_agent_resume_succeeded),[TYPE3]:entry(exports_agent_resume_failed)}});var exports_emit={};__export(exports_emit,{startSpan:()=>startSpan,shutdownEmitter:()=>shutdownEmitter,resumeEmitter:()=>resumeEmitter,isSpillJournalEmpty:()=>isSpillJournalEmpty,getEmitStats:()=>getEmitStats,flushNow:()=>flushNow,endSpan:()=>endSpan,emitEvent:()=>emitEvent,drainSpillJournalNow:()=>drainSpillJournalNow,__setSpillPathForTests:()=>__setSpillPathForTests,__resetEmitForTests:()=>__resetEmitForTests,__TEST_QUEUE_CAP:()=>__TEST_QUEUE_CAP,__TEST_BACKPRESSURE_WAIT_MS:()=>__TEST_BACKPRESSURE_WAIT_MS});import{createHash as createHash2,randomUUID as randomUUID3}from"crypto";import{appendFileSync,closeSync,existsSync as existsSync14,fsyncSync,mkdirSync as mkdirSync7,openSync,readFileSync as readFileSync10,renameSync as renameSync2,statSync as statSync2,unlinkSync as unlinkSync4}from"fs";import{homedir as homedir13}from"os";import{dirname as dirname6,join as join18}from"path";function getEmitStats(){return{...stats,queue_depth:queue.length}}function defaultSpillPath(){let home=process.env.GENIE_HOME??join18(homedir13(),".genie");return join18(home,"data","emit-spill.jsonl")}function __setSpillPathForTests(path2){spillPathOverride=path2}function spillPath(){return spillPathOverride??defaultSpillPath()}function ensureSpillDir(path2){let dir=dirname6(path2);if(!existsSync14(dir))mkdirSync7(dir,{recursive:!0})}function writeSpillRow(row){let path2=spillPath();ensureSpillDir(path2);let line=`${JSON.stringify(row)}
|
|
688
688
|
`,fd=openSync(path2,"a");try{appendFileSync(fd,line);try{fsyncSync(fd)}catch{}}finally{closeSync(fd)}if(stats.spilled_warn_plus++,firstSpillAt===null)firstSpillAt=Date.now()}function countSpillRows(){let path2=spillPath();if(!existsSync14(path2))return 0;try{let contents=readFileSync10(path2,"utf8");if(!contents)return 0;return contents.split(`
|
|
689
689
|
`).filter((l)=>l.length>0).length}catch{return 0}}function isSpillJournalEmpty(){return countSpillRows()===0}function readStagingRows(staging){let contents;try{contents=readFileSync10(staging,"utf8")}catch{return[]}let lines=contents.split(`
|
|
690
690
|
`).filter((l)=>l.length>0),rows=[];for(let line of lines)try{rows.push(JSON.parse(line))}catch{}return rows}function reappendRowsToJournal(path2,rows){let fd=openSync(path2,"a");try{for(let row of rows)appendFileSync(fd,`${JSON.stringify(row)}
|
|
@@ -802,9 +802,9 @@ ${errCtx.stack}`;d.reject(err)}else d.resolve(msg)}});return sub.requestSubject=
|
|
|
802
802
|
FROM hook_perf_baseline
|
|
803
803
|
ORDER BY p99_1h DESC NULLS LAST, sample_count_24h DESC
|
|
804
804
|
`).map((r)=>({...r,p50_1h:r.p50_1h===null?null:Number(r.p50_1h),p99_1h:r.p99_1h===null?null:Number(r.p99_1h),p50_24h:r.p50_24h===null?null:Number(r.p50_24h),p99_24h:r.p99_24h===null?null:Number(r.p99_24h),p50_7d:r.p50_7d===null?null:Number(r.p50_7d),p99_7d:r.p99_7d===null?null:Number(r.p99_7d),sample_count_24h:Number(r.sample_count_24h)}))}function detectRegressions(rows){let out=[];for(let r of rows){if(r.p99_1h===null||r.p99_7d===null)continue;if(r.p99_7d<=0)continue;let deltaPct=(r.p99_1h-r.p99_7d)/r.p99_7d*100;if(deltaPct>REGRESSION_PCT)out.push({handler:r.handler_name,tool:r.tool_name,event:r.event_name,p99_current_ms:r.p99_1h,p99_baseline_ms:r.p99_7d,delta_pct:deltaPct,severity:REGRESSION_SEVERITY})}return out}function formatMs(value){if(value===null)return"\u2014";return`${value.toFixed(2)}ms`}function printBaselineSection(rows){if(rows.length===0){console.log(" No `hook.delivery` spans found."),console.log(" \x1B[2mEnable telemetry: GENIE_WIDE_EMIT=1 (or wait for the daemon-mode default to take effect).\x1B[0m");return}console.log(" per-handler P50 / P99 over 1h, 24h, 7d (samples_24h):"),console.log();for(let row of rows){let tag=`${row.event_name}/${row.tool_name}/${row.handler_name}`,win=`1h ${formatMs(row.p50_1h)} / ${formatMs(row.p99_1h)} | 24h ${formatMs(row.p50_24h)} / ${formatMs(row.p99_24h)} | 7d ${formatMs(row.p50_7d)} / ${formatMs(row.p99_7d)}`;console.log(` ${tag.padEnd(46)} ${win} (n=${row.sample_count_24h})`)}}function printRegressionsSection(regressions){if(regressions.length===0){console.log(" \x1B[32m\u2713\x1B[0m no P99 regression > 50% vs 7d baseline");return}console.log(` \x1B[31m\u2717 [HIGH]\x1B[0m ${regressions.length} P99 regression(s) > 50% vs 7d baseline:`);for(let reg of regressions)console.log(` \x1B[31m\u2022\x1B[0m ${reg.event}/${reg.tool}/${reg.handler}: ${reg.p99_current_ms.toFixed(1)}ms (baseline ${reg.p99_baseline_ms.toFixed(1)}ms, +${reg.delta_pct.toFixed(0)}%)`)}function printFallbackSection(entries,logPath){if(entries.length===0){console.log(" \x1B[32m\u2713\x1B[0m no hook-socket fallback entries in the last 5 min");return}console.log(` \x1B[31m\u2717 [HIGH]\x1B[0m ${entries.length} hook-socket fallback entry/entries in the last 5 min:`),console.log(` \x1B[2mlog: ${logPath}\x1B[0m`);let sample=entries.slice(-5);for(let entry2 of sample)console.log(` \x1B[31m\u2022\x1B[0m ${entry2.ts} ${entry2.event??"?"}/${entry2.tool??"?"}: ${entry2.reason}${entry2.command?` \u2014 ${entry2.command}`:""}`);if(entries.length>5)console.log(` \x1B[2m\u2026 ${entries.length-5} earlier entr(y/ies) suppressed.\x1B[0m`)}function printHumanReport(report){console.log(),console.log("\x1B[1mHook Performance Baseline\x1B[0m"),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`),printBaselineSection(report.baseline),console.log(),printRegressionsSection(report.regressions),console.log(),printFallbackSection(report.recent_fallback_entries,report.fallback_log_path),console.log()}async function runPerfCheck(json2){let baseline=await loadBaseline(),regressions=detectRegressions(baseline),fallback=readRecentFallbackEntries().map((entry2)=>({...entry2,severity:FALLBACK_SEVERITY})),report={baseline,regressions,recent_fallback_entries:fallback,fallback_log_path:fallbackLogPath(),generated_at:new Date().toISOString()};if(json2)console.log(JSON.stringify(report,null,2));else printHumanReport(report);if(regressions.length>0||fallback.length>0)process.exit(1)}var REGRESSION_SEVERITY="HIGH",FALLBACK_SEVERITY="HIGH",REGRESSION_PCT=50,FALLBACK_WINDOW_SECONDS=300,_testExports;var init_perf_check=__esm(()=>{init_db();_testExports={readRecentFallbackEntries,detectRegressions}});var exports_archive_orphan_team_configs={};__export(exports_archive_orphan_team_configs,{classifyTeamDir:()=>classifyTeamDir,archiveOrphanTeamConfigs:()=>archiveOrphanTeamConfigs});import{existsSync as existsSync18,mkdirSync as mkdirSync8,readdirSync as readdirSync5,renameSync as renameSync3,statSync as statSync4}from"fs";import{homedir as homedir17}from"os";import{join as join22}from"path";function claudeConfigDir3(){return process.env.CLAUDE_CONFIG_DIR??join22(homedir17(),".claude")}function teamsBaseDir2(){return join22(claudeConfigDir3(),"teams")}function archiveBaseDir(){return join22(teamsBaseDir2(),"_archive")}function classifyTeamDir(dirPath,now=Date.now()){if(!existsSync18(dirPath))return"stale";if(existsSync18(join22(dirPath,"config.json")))return"has-config";let inboxes=join22(dirPath,"inboxes");if(!existsSync18(inboxes))return"stale";let entries;try{entries=readdirSync5(inboxes)}catch{return"stale"}if(entries.length===0)return"stale";for(let entry2 of entries){if(!entry2.endsWith(".json"))continue;let path2=join22(inboxes,entry2);try{let st=statSync4(path2);if(st.size<=2)continue;if(now-st.mtimeMs>ACTIVE_THRESHOLD_MS)continue;return"active"}catch{}}return"stale"}function archiveOrphanTeamConfigs(opts={}){let dryRun=opts.dryRun??!1,base=opts.baseDir??teamsBaseDir2(),now=opts.now??Date.now();if(!existsSync18(base))return[];let entries;try{entries=readdirSync5(base)}catch{return[]}let archiveBase=opts.baseDir?join22(opts.baseDir,"_archive"):archiveBaseDir(),decisions=[];for(let name of entries){if(name==="_archive"||name.startsWith("."))continue;let dirPath=join22(base,name),st;try{st=statSync4(dirPath)}catch{continue}if(!st.isDirectory())continue;let classification=classifyTeamDir(dirPath,now);if(classification==="has-config"){decisions.push({team:name,classification,reason:"config.json present"});continue}if(classification==="active"){decisions.push({team:name,classification,reason:"inbox messages newer than 24h \u2014 needs `genie team repair`"});continue}if(dryRun){decisions.push({team:name,classification,reason:"no recent inbox activity"});continue}if(!existsSync18(archiveBase))mkdirSync8(archiveBase,{recursive:!0});let ts3=Math.floor(now/1000),archivedTo=join22(archiveBase,`${name}-${ts3}`);try{renameSync3(dirPath,archivedTo),decisions.push({team:name,classification,reason:"archived (no recent inbox activity)",archivedTo})}catch(err){let msg=err instanceof Error?err.message:String(err);decisions.push({team:name,classification,reason:`archive failed: ${msg}`})}}return decisions}var ACTIVE_THRESHOLD_HOURS=24,ACTIVE_THRESHOLD_MS;var init_archive_orphan_team_configs=__esm(()=>{ACTIVE_THRESHOLD_MS=ACTIVE_THRESHOLD_HOURS*60*60*1000;if(import.meta.path===Bun.main){let dryRun=process.argv.slice(2).includes("--dry-run"),decisions=archiveOrphanTeamConfigs({dryRun});for(let d of decisions){let tag=d.classification==="stale"?dryRun?"WOULD ARCHIVE":"ARCHIVED":d.classification.toUpperCase();console.log(` [${tag}] ${d.team} \u2014 ${d.reason}${d.archivedTo?` \u2192 ${d.archivedTo}`:""}`)}console.log(`
|
|
805
|
-
${decisions.length} team dir${decisions.length===1?"":"s"} inspected`)}});var exports_session_capture={};__export(exports_session_capture,{setLiveWorkPending:()=>setLiveWorkPending,reconcileSubagentParents:()=>reconcileSubagentParents,liveWorkPending:()=>liveWorkPending,ingestFileFull:()=>ingestFileFull,ingestFile:()=>ingestFile,extractSubTool:()=>extractSubTool,discoverAllJsonlFiles:()=>discoverAllJsonlFiles,buildWorkerMap:()=>buildWorkerMap});import{open as open3,readdir as readdir4,stat as stat3}from"fs/promises";import{homedir as homedir18}from"os";import{basename as
|
|
805
|
+
${decisions.length} team dir${decisions.length===1?"":"s"} inspected`)}});var exports_session_capture={};__export(exports_session_capture,{setLiveWorkPending:()=>setLiveWorkPending,reconcileSubagentParents:()=>reconcileSubagentParents,liveWorkPending:()=>liveWorkPending,ingestFileFull:()=>ingestFileFull,ingestFile:()=>ingestFile,extractSubTool:()=>extractSubTool,discoverAllJsonlFiles:()=>discoverAllJsonlFiles,buildWorkerMap:()=>buildWorkerMap});import{open as open3,readdir as readdir4,stat as stat3}from"fs/promises";import{homedir as homedir18}from"os";import{basename as basename3,join as join23}from"path";function setLiveWorkPending(v){liveWorkPending=v}function truncateSubTool(value){if(!value)return null;return value.length>MAX_SUB_TOOL_LEN?value.slice(0,MAX_SUB_TOOL_LEN):value}function extractSubTool(toolName,input){let obj=input;switch(toolName){case"Bash":{let cmd=obj?.command??"";return truncateSubTool(cmd.split(`
|
|
806
806
|
`)[0]?.trim()||null)}case"Read":case"Write":case"Edit":return truncateSubTool(obj?.file_path||null);case"Grep":return truncateSubTool(obj?.pattern||null);case"Glob":return truncateSubTool(obj?.pattern||null);case"Agent":return truncateSubTool(obj?.subagent_type||null);case"Skill":return truncateSubTool(obj?.skill||null);default:return null}}function extractTextContent(content){if(typeof content==="string")return content;if(Array.isArray(content)){let texts=[];for(let block of content)if(typeof block==="string")texts.push(block);else if(block?.type==="text"&&typeof block.text==="string")texts.push(block.text);return texts.length>0?texts.join(`
|
|
807
|
-
`):null}return null}async function discoverMainSession(filePath,projectPath,name){try{let st=await stat3(filePath);return{sessionId:
|
|
807
|
+
`):null}return null}async function discoverMainSession(filePath,projectPath,name){try{let st=await stat3(filePath);return{sessionId:basename3(name,".jsonl"),jsonlPath:filePath,projectPath,parentSessionId:null,isSubagent:!1,mtime:Math.floor(st.mtimeMs),fileSize:st.size}}catch{return null}}async function discoverSubagentSessions(projectPath,parentName){let results=[],subagentsDir=join23(projectPath,parentName,"subagents");try{let subFiles=await readdir4(subagentsDir);for(let subFile of subFiles){if(!subFile.endsWith(".jsonl"))continue;try{let filePath=join23(subagentsDir,subFile),st=await stat3(filePath);results.push({sessionId:basename3(subFile,".jsonl"),jsonlPath:filePath,projectPath,parentSessionId:parentName,isSubagent:!0,mtime:Math.floor(st.mtimeMs),fileSize:st.size})}catch{}}}catch{}return results}async function discoverProjectSessions(projectPath){let results=[];try{let entries=await readdir4(projectPath,{withFileTypes:!0});for(let entry2 of entries){if(entry2.isFile()&&entry2.name.endsWith(".jsonl")){let file=await discoverMainSession(join23(projectPath,entry2.name),projectPath,entry2.name);if(file)results.push(file);continue}if(entry2.isDirectory()){let subs=await discoverSubagentSessions(projectPath,entry2.name);results.push(...subs)}}}catch{}return results}async function discoverAllJsonlFiles(){let claudeDir=join23(process.env.CLAUDE_CONFIG_DIR??join23(homedir18(),".claude"),"projects"),projects;try{projects=await readdir4(claudeDir)}catch{return[]}let results=[];for(let project of projects){let files=await discoverProjectSessions(join23(claudeDir,project));results.push(...files)}return results}async function buildWorkerMap(sql){if(workerMapCache&&Date.now()<workerMapCache.expires)return workerMapCache.map;let map2=new Map;try{let rows=await sql`
|
|
808
808
|
SELECT e.id as executor_id, e.agent_id, e.claude_session_id, a.team, a.wish_slug, a.task_id, a.role
|
|
809
809
|
FROM executors e
|
|
810
810
|
JOIN agents a ON e.agent_id = a.id
|
|
@@ -902,12 +902,12 @@ ${errCtx.stack}`;d.reject(err)}else d.resolve(msg)}});return sub.requestSubject=
|
|
|
902
902
|
processed_bytes = ${progress.processedBytes},
|
|
903
903
|
errors = ${progress.errors},
|
|
904
904
|
updated_at = now()
|
|
905
|
-
`}async function shouldSkipBackfill(sql){try{let existing=await sql`SELECT status FROM session_sync WHERE id = 'backfill'`;if(existing.length>0&&existing[0].status==="complete")return!0}catch{}try{let[{count}]=await sql`SELECT count(*)::int as count FROM sessions`;if(count>0){let existing=await sql`SELECT status FROM session_sync WHERE id = 'backfill'`;if(existing.length===0||existing[0].status==="complete")return!0}}catch{return!0}return!1}async function yieldToLiveWork(){while(liveWorkPending)await sleep2(LIVE_YIELD_POLL_MS)}async function getFileStartOffset(sql,file){let existing=await sql`SELECT last_ingested_offset FROM sessions WHERE id = ${file.sessionId}`;if(existing.length>0)return existing[0].last_ingested_offset??0;return 0}async function processBackfillFile(sql,file,progress,workerMap){let offset=await getFileStartOffset(sql,file);if(offset>=file.fileSize){progress.processedFiles++,progress.processedBytes+=file.fileSize;return}let currentOffset=offset;while(currentOffset<file.fileSize){await yieldToLiveWork();let result2=await ingestFile(sql,file.sessionId,file.jsonlPath,file.projectPath,currentOffset,{chunkSize:CHUNK_SIZE,parentSessionId:file.parentSessionId,isSubagent:file.isSubagent,fileSize:file.fileSize,mtime:file.mtime,workerMap});if(result2.newOffset<=currentOffset)break;progress.processedBytes+=result2.newOffset-currentOffset,currentOffset=result2.newOffset}progress.processedFiles++}async function processAllFiles(sql,allFiles,progress,workerMap){for(let file of allFiles){if(!running)break;await yieldToLiveWork();try{await processBackfillFile(sql,file,progress,workerMap)}catch(err){progress.errors++;let message=err instanceof Error?err.message:String(err);console.error(`[backfill] error on ${file.jsonlPath}: ${message}`)}if(progress.processedFiles%50===0)await updateSyncState(sql,progress);await sleep2(SLEEP_BETWEEN_FILES_MS)}}function resolveBackfillStatus(progress){if(!running)progress.status="paused",console.log(`[backfill] paused: ${progress.processedFiles}/${progress.totalFiles} files (will resume on next daemon start)`);else if(progress.errors>0&&progress.errors>=progress.totalFiles)progress.status="failed",console.error(`[backfill] failed: ${progress.errors}/${progress.totalFiles} files errored \u2014 will retry on next daemon start`);else progress.status="complete",console.log(`[backfill] complete: ${progress.processedFiles}/${progress.totalFiles} files, ${progress.errors} errors`)}async function startBackfill(sql){if(running)return;if(await shouldSkipBackfill(sql))return;running=!0,console.log("[backfill] starting session backfill...");try{let allFiles=await discoverAllJsonlFiles();allFiles.sort(compareBackfillFiles);let totalBytes=allFiles.reduce((sum,f)=>sum+f.fileSize,0),progress={totalFiles:allFiles.length,processedFiles:0,totalBytes,processedBytes:0,errors:0,status:"running"};await updateSyncState(sql,progress),console.log(`[backfill] discovered ${allFiles.length} files (${(totalBytes/1024/1024).toFixed(1)} MB)`);let workerMap=await buildWorkerMap(sql);await processAllFiles(sql,allFiles,progress,workerMap);try{let{linked,metadataFilled}=await reconcileSubagentParents(sql);if(linked>0)console.log(`[backfill] reconciled parent_session_id for ${linked} subagent(s)`);if(metadataFilled>0)console.log(`[backfill] inherited parent metadata for ${metadataFilled} subagent(s)`)}catch(err){let message=err instanceof Error?err.message:String(err);console.warn(`[backfill] parent reconcile skipped: ${message}`)}resolveBackfillStatus(progress),await updateSyncState(sql,progress)}catch(err){let message=err instanceof Error?err.message:String(err);console.error(`[backfill] fatal error: ${message}`)}finally{running=!1}}function stopBackfill(){running=!1}async function getBackfillStatus(sql){try{let rows=await sql`SELECT * FROM session_sync WHERE id = 'backfill'`;if(rows.length===0)return null;let row=rows[0];return{totalFiles:row.total_files,processedFiles:row.processed_files,totalBytes:row.total_bytes,processedBytes:row.processed_bytes,errors:row.errors,status:row.status}}catch{return null}}var CHUNK_SIZE=65536,SLEEP_BETWEEN_FILES_MS=100,LIVE_YIELD_POLL_MS=200,running=!1;var init_session_backfill=__esm(()=>{init_session_capture()});var exports_ensure_ready={};__export(exports_ensure_ready,{runDoctorMaintenance:()=>runDoctorMaintenance,ensureServeReady:()=>ensureServeReady,defaultScanTeamConfigOrphans:()=>defaultScanTeamConfigOrphans,defaultRunBackfillBlocking:()=>defaultRunBackfillBlocking,defaultArchiveStaleTeamConfigs:()=>defaultArchiveStaleTeamConfigs,BACKFILL_DRIFT_THRESHOLD_PCT:()=>BACKFILL_DRIFT_THRESHOLD_PCT});import{spawnSync}from"child_process";import{existsSync as existsSync19,mkdirSync as mkdirSync9,readdirSync as readdirSync6,renameSync as renameSync4,statSync as statSync5}from"fs";import{homedir as homedir19}from"os";import{dirname as
|
|
905
|
+
`}async function shouldSkipBackfill(sql){try{let existing=await sql`SELECT status FROM session_sync WHERE id = 'backfill'`;if(existing.length>0&&existing[0].status==="complete")return!0}catch{}try{let[{count}]=await sql`SELECT count(*)::int as count FROM sessions`;if(count>0){let existing=await sql`SELECT status FROM session_sync WHERE id = 'backfill'`;if(existing.length===0||existing[0].status==="complete")return!0}}catch{return!0}return!1}async function yieldToLiveWork(){while(liveWorkPending)await sleep2(LIVE_YIELD_POLL_MS)}async function getFileStartOffset(sql,file){let existing=await sql`SELECT last_ingested_offset FROM sessions WHERE id = ${file.sessionId}`;if(existing.length>0)return existing[0].last_ingested_offset??0;return 0}async function processBackfillFile(sql,file,progress,workerMap){let offset=await getFileStartOffset(sql,file);if(offset>=file.fileSize){progress.processedFiles++,progress.processedBytes+=file.fileSize;return}let currentOffset=offset;while(currentOffset<file.fileSize){await yieldToLiveWork();let result2=await ingestFile(sql,file.sessionId,file.jsonlPath,file.projectPath,currentOffset,{chunkSize:CHUNK_SIZE,parentSessionId:file.parentSessionId,isSubagent:file.isSubagent,fileSize:file.fileSize,mtime:file.mtime,workerMap});if(result2.newOffset<=currentOffset)break;progress.processedBytes+=result2.newOffset-currentOffset,currentOffset=result2.newOffset}progress.processedFiles++}async function processAllFiles(sql,allFiles,progress,workerMap){for(let file of allFiles){if(!running)break;await yieldToLiveWork();try{await processBackfillFile(sql,file,progress,workerMap)}catch(err){progress.errors++;let message=err instanceof Error?err.message:String(err);console.error(`[backfill] error on ${file.jsonlPath}: ${message}`)}if(progress.processedFiles%50===0)await updateSyncState(sql,progress);await sleep2(SLEEP_BETWEEN_FILES_MS)}}function resolveBackfillStatus(progress){if(!running)progress.status="paused",console.log(`[backfill] paused: ${progress.processedFiles}/${progress.totalFiles} files (will resume on next daemon start)`);else if(progress.errors>0&&progress.errors>=progress.totalFiles)progress.status="failed",console.error(`[backfill] failed: ${progress.errors}/${progress.totalFiles} files errored \u2014 will retry on next daemon start`);else progress.status="complete",console.log(`[backfill] complete: ${progress.processedFiles}/${progress.totalFiles} files, ${progress.errors} errors`)}async function startBackfill(sql){if(running)return;if(await shouldSkipBackfill(sql))return;running=!0,console.log("[backfill] starting session backfill...");try{let allFiles=await discoverAllJsonlFiles();allFiles.sort(compareBackfillFiles);let totalBytes=allFiles.reduce((sum,f)=>sum+f.fileSize,0),progress={totalFiles:allFiles.length,processedFiles:0,totalBytes,processedBytes:0,errors:0,status:"running"};await updateSyncState(sql,progress),console.log(`[backfill] discovered ${allFiles.length} files (${(totalBytes/1024/1024).toFixed(1)} MB)`);let workerMap=await buildWorkerMap(sql);await processAllFiles(sql,allFiles,progress,workerMap);try{let{linked,metadataFilled}=await reconcileSubagentParents(sql);if(linked>0)console.log(`[backfill] reconciled parent_session_id for ${linked} subagent(s)`);if(metadataFilled>0)console.log(`[backfill] inherited parent metadata for ${metadataFilled} subagent(s)`)}catch(err){let message=err instanceof Error?err.message:String(err);console.warn(`[backfill] parent reconcile skipped: ${message}`)}resolveBackfillStatus(progress),await updateSyncState(sql,progress)}catch(err){let message=err instanceof Error?err.message:String(err);console.error(`[backfill] fatal error: ${message}`)}finally{running=!1}}function stopBackfill(){running=!1}async function getBackfillStatus(sql){try{let rows=await sql`SELECT * FROM session_sync WHERE id = 'backfill'`;if(rows.length===0)return null;let row=rows[0];return{totalFiles:row.total_files,processedFiles:row.processed_files,totalBytes:row.total_bytes,processedBytes:row.processed_bytes,errors:row.errors,status:row.status}}catch{return null}}var CHUNK_SIZE=65536,SLEEP_BETWEEN_FILES_MS=100,LIVE_YIELD_POLL_MS=200,running=!1;var init_session_backfill=__esm(()=>{init_session_capture()});var exports_ensure_ready={};__export(exports_ensure_ready,{runDoctorMaintenance:()=>runDoctorMaintenance,ensureServeReady:()=>ensureServeReady,defaultScanTeamConfigOrphans:()=>defaultScanTeamConfigOrphans,defaultRunBackfillBlocking:()=>defaultRunBackfillBlocking,defaultArchiveStaleTeamConfigs:()=>defaultArchiveStaleTeamConfigs,BACKFILL_DRIFT_THRESHOLD_PCT:()=>BACKFILL_DRIFT_THRESHOLD_PCT});import{spawnSync}from"child_process";import{existsSync as existsSync19,mkdirSync as mkdirSync9,readdirSync as readdirSync6,renameSync as renameSync4,statSync as statSync5}from"fs";import{homedir as homedir19}from"os";import{dirname as dirname7,join as join24}from"path";import{fileURLToPath as fileURLToPath2}from"url";function claudeConfigDir4(){return process.env.CLAUDE_CONFIG_DIR??join24(homedir19(),".claude")}function teamsBaseDir3(){return join24(claudeConfigDir4(),"teams")}async function defaultRunPartitionMaintenance(){let r=(await(await getConnection())`SELECT genie_runtime_events_maintain_partitions(2, 30)::jsonb AS r`)[0]?.r??{created_or_present:0,dropped:0,next_rotation_at:null};return{createdOrPresent:r.created_or_present,dropped:r.dropped,nextRotationAt:r.next_rotation_at}}function resolveWatchdogCliPath(){try{let dir=dirname7(fileURLToPath2(import.meta.url));for(let i2=0;i2<8;i2++){let candidate=join24(dir,"packages/watchdog/src/cli.ts");if(existsSync19(candidate))return candidate;let parent=dirname7(dir);if(parent===dir)break;dir=parent}}catch{}return null}async function defaultInstallWatchdog(){let overrideCmd=process.env.GENIE_WATCHDOG_INSTALL_CMD;if(overrideCmd){let result3=spawnSync(overrideCmd,[],{stdio:"pipe",encoding:"utf8",shell:!0});if(result3.status!==0){let stderr=(result3.stderr??"").toString().trim(),stdout=(result3.stdout??"").toString().trim();throw Error(stderr||stdout||`watchdog install exited ${result3.status}`)}return{filesWritten:[],filesSkipped:[]}}let cliPath=resolveWatchdogCliPath();if(!cliPath)throw Error("watchdog CLI not found relative to genie install \u2014 set GENIE_WATCHDOG_INSTALL_CMD or run from the source repo");let result2=spawnSync("bun",["run",cliPath,"install"],{stdio:"pipe",encoding:"utf8"});if(result2.status!==0){let stderr=(result2.stderr??"").toString().trim(),stdout=(result2.stdout??"").toString().trim();throw Error(stderr||stdout||`watchdog install exited ${result2.status}`)}return{filesWritten:[],filesSkipped:[]}}async function defaultMeasureBackfillDrift(){if(!await isAvailable())return{driftPct:null,detail:"pg unavailable \u2014 skipped drift probe"};try{let rows=await(await getConnection())`
|
|
906
906
|
SELECT status, total_bytes, processed_bytes
|
|
907
907
|
FROM session_sync
|
|
908
908
|
WHERE id = 'backfill'
|
|
909
909
|
LIMIT 1
|
|
910
|
-
`;if(rows.length===0)return{driftPct:null,detail:"no prior backfill row \u2014 first run will seed"};let row=rows[0];if(row.total_bytes<=0)return{driftPct:0,detail:"no JSONL bytes discovered yet"};let pct=Math.max(0,row.total_bytes-row.processed_bytes)/row.total_bytes*100,display=pct.toFixed(1);return{driftPct:pct,detail:`processed ${row.processed_bytes}/${row.total_bytes} bytes (drift ${display}%)`}}catch(err){return{driftPct:null,detail:`drift probe failed: ${err.message}`}}}async function defaultRunBackfillSync(){if(!await isAvailable())return{ranSync:!1,driftPct:null,detail:"pg unavailable \u2014 backfill skipped"};return(async()=>{try{let sql=await getConnection(),{startBackfill:startBackfill2}=await Promise.resolve().then(() => (init_session_backfill(),exports_session_backfill));await startBackfill2(sql)}catch{}})(),{ranSync:!0,driftPct:null,detail:"background convergence kicked \u2014 `genie doctor --fix` to wait"}}async function defaultRunBackfillBlocking(){if(!await isAvailable())return{ranSync:!1,driftPct:null,detail:"pg unavailable \u2014 backfill skipped"};let sql=await getConnection(),{startBackfill:startBackfill2}=await Promise.resolve().then(() => (init_session_backfill(),exports_session_backfill));await startBackfill2(sql);let after=await defaultMeasureBackfillDrift();return{ranSync:!0,driftPct:after.driftPct,detail:after.detail}}async function defaultListOrphanedZombies(){try{let{listExhaustedZombies:listExhaustedZombies2}=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry));return await listExhaustedZombies2()}catch{return[]}}function safeIsDirectory(path2){try{return statSync5(path2).isDirectory()}catch{return!1}}function summarizeInboxes(inboxesDir2){let inboxFiles=[];try{inboxFiles=readdirSync6(inboxesDir2).filter((f)=>f.endsWith(".json"))}catch{return{newestMs:null,hasContent:!1}}let newestMs=null,hasContent=!1;for(let f of inboxFiles)try{let st=statSync5(join24(inboxesDir2,f));if(newestMs===null||st.mtimeMs>newestMs)newestMs=st.mtimeMs;if(st.size>2)hasContent=!0}catch{}return{newestMs,hasContent}}function classifyTeamDir2(name,base,now){let dir=join24(base,name);if(!safeIsDirectory(dir))return null;if(existsSync19(join24(dir,"config.json")))return null;let inboxesDir2=join24(dir,"inboxes");if(!safeIsDirectory(inboxesDir2))return null;let{newestMs,hasContent}=summarizeInboxes(inboxesDir2),orphan={teamName:name,path:dir,newestInboxMs:newestMs,hasContent},active=hasContent&&newestMs!==null&&now-newestMs<ORPHAN_FRESH_WINDOW_MS;return{orphan,active}}function defaultScanTeamConfigOrphans(){let base=teamsBaseDir3(),result2={active:[],stale:[]};if(!existsSync19(base))return result2;let now=Date.now();for(let name of readdirSync6(base)){if(name.startsWith(".")||name==="_archive")continue;let classified=classifyTeamDir2(name,base,now);if(!classified)continue;(classified.active?result2.active:result2.stale).push(classified.orphan)}return result2}function defaultArchiveStaleTeamConfigs(orphans){if(orphans.length===0)return[];let archiveRoot=join24(teamsBaseDir3(),"_archive");mkdirSync9(archiveRoot,{recursive:!0});let ts3=new Date().toISOString().replace(/[:.]/g,"-"),archived=[];for(let o of orphans){let dest=join24(archiveRoot,`${o.teamName}-${ts3}`);try{renameSync4(o.path,dest),archived.push(dest)}catch{}}return archived}async function defaultRecordAudit(eventType,name,details){await recordAuditEvent("command","serve_start",eventType,"serve",{precondition:name,...details})}async function checkPartition(health,autoFix,deps){if(health.partition_health==="ok"||health.partition_health==="warn")return{name:"partition",status:"ok",detail:health.next_rotation_at?`next rotation: ${health.next_rotation_at}`:void 0};if(health.partition_health==="unknown")return{name:"partition",status:"skipped",detail:"pg unavailable \u2014 skipping partition probe"};if(!autoFix)return{name:"partition",status:"refused",detail:"today's partition is missing or rotation is overdue",fixCommand:"genie doctor --observability # then re-run; or `genie serve start` (without --no-fix)"};let result2=await deps.runPartitionMaintenance();return{name:"partition",status:"fixed",detail:`created/present ${result2.createdOrPresent}, dropped ${result2.dropped}; next rotation ${result2.nextRotationAt??"unknown"}`}}async function checkWatchdog(health,autoFix,deps){if(deps.platform!=="linux")return{name:"watchdog",status:"skipped",detail:"watchdog install is Linux/systemd only"};if(health.watchdog==="ok")return{name:"watchdog",status:"ok"};if(!autoFix)return{name:"watchdog",status:"refused",detail:health.watchdog_detail??"watchdog units missing",fixCommand:"sudo bun run packages/watchdog/src/cli.ts install"};try{let result2=await deps.installWatchdog();return{name:"watchdog",status:"fixed",detail:`wrote ${result2.filesWritten.length}, skipped ${result2.filesSkipped.length}`}}catch(err){return{name:"watchdog",status:"refused",detail:`auto-install failed: ${err.message}`,fixCommand:"sudo bun run packages/watchdog/src/cli.ts install"}}}async function checkBackfill(autoFix,deps){let drift=await deps.measureBackfillDrift();if(drift.driftPct===null)return{name:"backfill",status:"skipped",detail:drift.detail};if(drift.driftPct<BACKFILL_DRIFT_THRESHOLD_PCT)return{name:"backfill",status:"ok",detail:drift.detail};if(!autoFix)return{name:"backfill",status:"refused",detail:drift.detail,fixCommand:`genie sessions sync # drift ${drift.driftPct.toFixed(1)}% > ${BACKFILL_DRIFT_THRESHOLD_PCT}%`};return{name:"backfill",status:"fixed",detail:(await deps.runBackfillSync()).detail}}async function checkDeadPaneZombies(deps){let orphans=await deps.listOrphanedZombies();if(orphans.length===0)return{name:"dead_pane_zombies",status:"ok"};return{name:"dead_pane_zombies",status:"refused",detail:`${orphans.length} exhausted zombie(s) past TTL; visible in \`genie status\``,fixCommand:"genie prune --zombies # archive eligible rows"}}function checkTeamConfigOrphans(autoFix,deps){let scan=deps.scanTeamConfigOrphans();if(scan.active.length===0&&scan.stale.length===0)return{name:"team_config_orphans",status:"ok"};if(!autoFix){let summary=`active=${scan.active.length} stale=${scan.stale.length}`,firstActive=scan.active[0]?.teamName;return{name:"team_config_orphans",status:"refused",detail:summary,fixCommand:firstActive?`genie team repair ${firstActive} # active orphan; stale dirs archive on auto-fix`:"genie serve start # auto-fix archives stale orphans"}}let archivedPaths=deps.archiveStaleTeamConfigs(scan.stale);if(scan.active.length>0)return{name:"team_config_orphans",status:"refused",detail:`archived ${archivedPaths.length} stale; ${scan.active.length} active orphan(s) need repair`,fixCommand:`genie team repair ${scan.active[0].teamName}`};return{name:"team_config_orphans",status:"fixed",detail:`archived ${archivedPaths.length} stale orphan(s)`}}function bindDefaults(deps){return{collectHealth:deps?.collectHealth??collectObservabilityHealth,runPartitionMaintenance:deps?.runPartitionMaintenance??defaultRunPartitionMaintenance,installWatchdog:deps?.installWatchdog??defaultInstallWatchdog,runBackfillSync:deps?.runBackfillSync??defaultRunBackfillSync,measureBackfillDrift:deps?.measureBackfillDrift??defaultMeasureBackfillDrift,listOrphanedZombies:deps?.listOrphanedZombies??defaultListOrphanedZombies,scanTeamConfigOrphans:deps?.scanTeamConfigOrphans??defaultScanTeamConfigOrphans,archiveStaleTeamConfigs:deps?.archiveStaleTeamConfigs??defaultArchiveStaleTeamConfigs,platform:deps?.platform??process.platform,recordAudit:deps?.recordAudit??defaultRecordAudit,log:deps?.log??((line)=>console.log(line))}}async function ensureServeReady(opts){let deps=bindDefaults(opts.deps),health=await deps.collectHealth(),results=[];results.push(await checkPartition(health,opts.autoFix,deps)),results.push(await checkBackfill(opts.autoFix,deps)),results.push(await checkDeadPaneZombies(deps)),await emitAuditEvents(results,deps);let ok=results.every((r)=>r.status==="ok"||r.status==="fixed"||r.status==="skipped");return printReport(results,deps.log),{ok,results}}function formatDuration(ms){if(ms<1000)return`${ms}ms`;return`${(ms/1000).toFixed(1)}s`}function logMaintenanceStepStart(log,silent,label){if(!silent)log(` ${label}...`);return Date.now()}function logMaintenanceStepDone(log,silent,label,startedAt){if(!silent)log(` done ${label} (${formatDuration(Date.now()-startedAt)})`)}async function runDoctorMaintenance(opts={}){let rawRunBackfillSync=opts.deps?.runBackfillSync??defaultRunBackfillBlocking,deps=bindDefaults({...opts.deps,runBackfillSync:defaultRunBackfillBlocking,log:opts.silent?()=>{}:opts.deps?.log});deps.runBackfillSync=async()=>{let startedAt2=logMaintenanceStepStart(deps.log,opts.silent,"Running session backfill convergence (can take minutes on large transcript history)");try{return await rawRunBackfillSync()}finally{logMaintenanceStepDone(deps.log,opts.silent,"session backfill convergence",startedAt2)}};let startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Collecting observability health"),health=await deps.collectHealth();logMaintenanceStepDone(deps.log,opts.silent,"observability health",startedAt);let results=[];startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking runtime event partitions"),results.push(await checkPartition(health,!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"runtime event partitions",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking watchdog install"),results.push(await checkWatchdog(health,!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"watchdog install",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking session backfill drift"),results.push(await checkBackfill(!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"session backfill drift",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking exhausted zombie rows"),results.push(await checkDeadPaneZombies(deps)),logMaintenanceStepDone(deps.log,opts.silent,"exhausted zombie rows",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking Claude team config orphans"),results.push(checkTeamConfigOrphans(!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"Claude team config orphans",startedAt),await emitAuditEvents(results,deps);let ok=results.every((r)=>r.status==="ok"||r.status==="fixed"||r.status==="skipped");return printReport(results,deps.log),{ok,results}}async function emitAuditEvents(results,deps){for(let result2 of results)if(result2.status==="fixed")await deps.recordAudit("serve.precondition.fixed",result2.name,{detail:result2.detail??null}).catch(()=>{});else if(result2.status==="refused")await deps.recordAudit("serve.precondition.refused",result2.name,{detail:result2.detail??null,fix_command:result2.fixCommand??null}).catch(()=>{})}function printReport(results,log){log(" Preconditions:");for(let r of results){let tag=statusTag(r.status),suffix=r.detail?` \u2014 ${r.detail}`:"";if(log(` ${tag} ${r.name}${suffix}`),r.status==="refused"&&r.fixCommand)log(` \u2192 ${r.fixCommand}`)}}function statusTag(status){switch(status){case"ok":return"[ok]";case"fixed":return"[fix]";case"refused":return"[!!]";case"skipped":return"[--]"}}var BACKFILL_DRIFT_THRESHOLD_PCT=5,ORPHAN_FRESH_WINDOW_MS=86400000;var init_ensure_ready=__esm(()=>{init_observability_health();init_audit();init_db()});var exports_doctor={};__export(exports_doctor,{runPostUpdateMaintenance:()=>runPostUpdateMaintenance,findBundledTmuxConfigDir:()=>findBundledTmuxConfigDir,doctorCommand:()=>doctorCommand,checkTmuxConfigs:()=>checkTmuxConfigs,checkLegacyAgentFrontmatter:()=>checkLegacyAgentFrontmatter,checkGenieAgentTemplate:()=>checkGenieAgentTemplate});import{copyFileSync as copyFileSync2,existsSync as existsSync20,mkdirSync as mkdirSync10,readFileSync as readFileSync13,readdirSync as readdirSync7,statSync as statSync6,unlinkSync as unlinkSync6,writeFileSync as writeFileSync7}from"fs";import{homedir as homedir20}from"os";import{dirname as dirname7,join as join25,resolve as resolve3}from"path";import{fileURLToPath as fileURLToPath3}from"url";var{$:$3}=globalThis.Bun;function printSectionHeader(title){console.log(),console.log(`\x1B[1m${title}:\x1B[0m`)}function printCheckResult(result2){let icon={pass:"\x1B[32m\u2713\x1B[0m",fail:"\x1B[31m\u2717\x1B[0m",warn:"\x1B[33m!\x1B[0m"}[result2.status],message=result2.message?` ${result2.message}`:"";if(console.log(` ${icon} ${result2.name}${message}`),result2.suggestion)console.log(` \x1B[2m${result2.suggestion}\x1B[0m`)}async function checkPrerequisites(){let results=[],tmuxCheck=await checkCommand("tmux");if(tmuxCheck.exists)results.push({name:"tmux",status:"pass",message:tmuxCheck.version||""});else results.push({name:"tmux",status:"fail",suggestion:"Install with: brew install tmux (or apt install tmux)"});let jqCheck=await checkCommand("jq");if(jqCheck.exists)results.push({name:"jq",status:"pass",message:jqCheck.version||""});else results.push({name:"jq",status:"fail",suggestion:"Install with: brew install jq (or apt install jq)"});let bunCheck=await checkCommand("bun");if(bunCheck.exists)results.push({name:"bun",status:"pass",message:bunCheck.version||""});else results.push({name:"bun",status:"fail",suggestion:"Install with: curl -fsSL https://bun.sh/install | bash"});let claudeCheck=await checkCommand("claude");if(claudeCheck.exists)results.push({name:"Claude Code",status:"pass",message:claudeCheck.version||""});else results.push({name:"Claude Code",status:"warn",suggestion:"Install with: npm install -g @anthropic-ai/claude-code"});let codexCheck=await checkCommand("codex");if(codexCheck.exists)results.push({name:"Codex CLI",status:"pass",message:codexCheck.version||""});else results.push({name:"Codex CLI",status:"warn",suggestion:"Install via OpenAI account; codex is optional unless using --provider codex"});let requiredForSpawn=["genie","bun","node","npm","git","claude","codex"];for(let bin of requiredForSpawn){let interactivePath=await resolveBinaryInteractive(bin),nonInteractivePath=await resolveBinaryNonInteractive(bin);if(interactivePath&&nonInteractivePath)results.push({name:`Non-interactive PATH: ${bin}`,status:"pass",message:nonInteractivePath});else if(interactivePath&&!nonInteractivePath)results.push({name:`Non-interactive PATH: ${bin}`,status:"warn",message:"interactive-only",suggestion:`Move PATH export from ~/.bashrc to ~/.profile so spawn-scripts can resolve ${bin}. (Or use a stable symlink in ~/.local/bin.)`});else if(!interactivePath&&bin!=="codex"){if(bin==="genie"||bin==="node"||bin==="npm"||bin==="git")results.push({name:`Non-interactive PATH: ${bin}`,status:"warn",message:"not in non-interactive PATH",suggestion:`Add ${bin} to ~/.profile (not just ~/.bashrc). Some flows (e.g. genie update) shell out to bare '${bin}' from non-interactive subprocesses.`})}}return results}async function resolveBinaryInteractive(bin){try{return(await $3`command -v ${bin}`.quiet().text()).trim()||null}catch{return null}}async function resolveBinaryNonInteractive(bin){try{return(await $3`sh -c "command -v ${bin}"`.quiet().text()).trim()||null}catch{return null}}async function checkConfiguration(){let results=[];if(genieConfigExists())results.push({name:"Genie config exists",status:"pass",message:contractClaudePath(getGenieConfigPath())});else results.push({name:"Genie config exists",status:"warn",message:"not found",suggestion:"Run: genie setup"});if(isSetupComplete())results.push({name:"Setup complete",status:"pass"});else results.push({name:"Setup complete",status:"warn",message:"not completed",suggestion:"Run: genie setup"});let claudeSettingsPath=getClaudeSettingsPath();if(existsSync20(claudeSettingsPath))results.push({name:"Claude settings exists",status:"pass",message:contractClaudePath(claudeSettingsPath)});else results.push({name:"Claude settings exists",status:"warn",message:"not found",suggestion:"Claude Code creates this on first run"});return results}async function checkTmux(){let results=[];try{if((await $3`${tmuxBin()} -L genie list-sessions 2>/dev/null`.quiet()).exitCode===0)results.push({name:"Server running",status:"pass"});else return results.push({name:"Server running",status:"warn",message:"no sessions",suggestion:"Start with: tmux new-session -d -s genie"}),results}catch{return results.push({name:"Server running",status:"warn",message:"could not check"}),results}let sessionName=(await loadGenieConfig()).session.name;try{if((await $3`${tmuxBin()} -L genie has-session -t ${`=${sessionName}`} 2>/dev/null`.quiet()).exitCode===0)results.push({name:`Session '${sessionName}' exists`,status:"pass"});else results.push({name:`Session '${sessionName}' exists`,status:"warn",suggestion:`Start with: tmux new-session -d -s ${sessionName}`})}catch{results.push({name:`Session '${sessionName}' exists`,status:"warn",message:"could not check"})}return results}async function checkWorkerProfiles(){let results=[];if(!genieConfigExists())return results.push({name:"Worker profiles",status:"warn",message:"no genie config",suggestion:"Run: genie setup"}),results;let config=await loadGenieConfig(),profiles=config.workerProfiles;if(!profiles||Object.keys(profiles).length===0)return results.push({name:"Worker profiles",status:"pass",message:"none configured (using defaults)"}),results;let totalProfiles=Object.keys(profiles).length;results.push({name:"Profiles configured",status:"pass",message:`${totalProfiles} profile${totalProfiles===1?"":"s"}`});for(let name of Object.keys(profiles))results.push({name:`Profile '${name}'`,status:"pass",message:"claude (direct)"});if(config.defaultWorkerProfile)if(profiles[config.defaultWorkerProfile])results.push({name:"Default profile",status:"pass",message:config.defaultWorkerProfile});else results.push({name:"Default profile",status:"warn",message:`'${config.defaultWorkerProfile}' not found`,suggestion:"Run: genie profiles default <profile>"});return results}async function checkBridge(){let results=[];try{let{getBridgeStatus:getBridgeStatus2,removeBridgePidfile:removeBridgePidfile2}=await Promise.resolve().then(() => (init_bridge_status(),exports_bridge_status)),res=await getBridgeStatus2(void 0,{});if(res.state==="stopped")return results.push({name:"Bridge",status:"warn",message:"stopped (no pidfile)",suggestion:"Start the bridge with: genie serve"}),results;if(res.state==="stale"){if(res.pidfile)removeBridgePidfile2();return results.push({name:"Bridge",status:"fail",message:`stale: ${res.detail}`,suggestion:"Restart the bridge with: genie serve restart"}),results}let{pong,pidfile}=res;if(!pong||!pidfile)return results.push({name:"Bridge",status:"warn",message:"running state missing pong/pidfile metadata"}),results;let uptimeSec=Math.round(pong.uptimeMs/1000);results.push({name:"Bridge running",status:"pass",message:`running (pid ${pong.pid}, uptime ${uptimeSec}s)`}),results.push({name:"NATS ping",status:"pass",message:`pong in ${res.latencyMs??0}ms (${pidfile.natsUrl})`}),results.push({name:"Subjects",status:"pass",message:pong.subjects.join(", ")})}catch(err){let detail=err instanceof Error?err.message:String(err);results.push({name:"Bridge module",status:"warn",message:`could not probe bridge: ${detail}`})}return results}function checkGenieAgentTemplate(workspaceRoot){let root=workspaceRoot??findWorkspace()?.root;if(!root)return[];let genieDir=join25(root,"agents","genie");if(!existsSync20(genieDir))return[];let agentsMd=join25(genieDir,"AGENTS.md"),agentYaml=join25(genieDir,"agent.yaml"),issues=[];if(existsSync20(agentsMd))try{if(readFileSync13(agentsMd,"utf-8").includes(STALE_GENIE_AGENTS_MD_MARKER))issues.push("AGENTS.md uses generic placeholder template")}catch{}if(existsSync20(agentYaml))try{let text=readFileSync13(agentYaml,"utf-8");if(!STALE_GENIE_AGENT_YAML_MISSING_MODEL_REGEX.test(text))issues.push("agent.yaml missing model field (TUI falls back to gray)")}catch{}if(issues.length===0)return[{name:"agents/genie scaffold up to date",status:"pass"}];return[{name:"agents/genie stale scaffold",status:"warn",message:issues.join("; "),suggestion:"Run: genie doctor --fix (re-emits genie specialist templates, preserves user edits)"}]}function findBundledTmuxConfigDir(){try{let moduleDir=dirname7(fileURLToPath3(import.meta.url));for(let i2=0;i2<6;i2+=1){let candidate=resolve3(moduleDir,"../".repeat(i2+1),"scripts","tmux");if(existsSync20(join25(candidate,"tui-tmux.conf"))&&existsSync20(join25(candidate,"genie.tmux.conf")))return candidate}}catch{}return null}function checkTmuxConfigs(){if(!findBundledTmuxConfigDir())return[{name:"tmux configs",status:"pass",message:"bundled configs unavailable (skipped)"}];let home=join25(homedir20(),".genie"),stale=[],expectedSnippet="unbind -n MouseDown3Pane";for(let file of["tui-tmux.conf","tmux.conf"]){let installedPath=join25(home,file);if(!existsSync20(installedPath))continue;try{if(!readFileSync13(installedPath,"utf-8").includes(expectedSnippet))stale.push(file)}catch{stale.push(file)}}if(stale.length===0)return[{name:"~/.genie tmux configs up to date",status:"pass"}];return[{name:"~/.genie tmux configs stale",status:"warn",message:`missing right-click unbind in: ${stale.join(", ")}`,suggestion:"Run: genie doctor --fix (refreshes ~/.genie tmux configs from bundled scripts/tmux/)"}]}function isAgentDirectory(path2){try{return statSync6(path2).isDirectory()}catch{return!1}}function hasLegacyFrontmatter(agentDir){let yamlPath=join25(agentDir,"agent.yaml"),agentsMdPath=join25(agentDir,"AGENTS.md");if(!existsSync20(yamlPath)||!existsSync20(agentsMdPath))return!1;try{return readFileSync13(agentsMdPath,"utf-8").slice(0,4).startsWith("---")}catch{return!1}}function checkLegacyAgentFrontmatter(workspaceRoot){let results=[],root=workspaceRoot??findWorkspace()?.root;if(!root)return[];let agentsDir=join25(root,"agents");if(!existsSync20(agentsDir))return[];let entries;try{entries=readdirSync7(agentsDir)}catch{return[]}for(let name of entries){let agentDir=join25(agentsDir,name);if(!isAgentDirectory(agentDir))continue;if(!hasLegacyFrontmatter(agentDir))continue;results.push({name:`agents/${name}/AGENTS.md`,status:"warn",message:"legacy frontmatter detected (ignored by sync)",suggestion:`Move config into agents/${name}/agent.yaml \u2014 AGENTS.md is prompt-only post-migration.`})}if(results.length===0)results.push({name:"No legacy frontmatter in agents/*/AGENTS.md",status:"pass"});return results}function runCheckSection(label,results,counts){printSectionHeader(label);for(let result2 of results){if(printCheckResult(result2),result2.status==="fail")counts.errors=!0;if(result2.status==="warn")counts.warnings=!0}}async function doctorCommand(options){if(options?.fix){await doctorFix();return}if(options?.fixTeamOrphans){await runFixTeamOrphans({dryRun:Boolean(options.dryRun),json:Boolean(options.json)});return}if(options?.observability){await runObservabilityCheck(Boolean(options.json));return}if(options?.perf){let{runPerfCheck:runPerfCheck2}=await Promise.resolve().then(() => (init_perf_check(),exports_perf_check));await runPerfCheck2(Boolean(options.json));return}console.log(),console.log("\x1B[1mGenie Doctor\x1B[0m"),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`);let counts={errors:!1,warnings:!1};if(runCheckSection("Prerequisites",await checkPrerequisites(),counts),runCheckSection("Installer Resolution",await collectInstallerResolution(),counts),runCheckSection("Configuration",await checkConfiguration(),counts),runCheckSection("Tmux",await checkTmux(),counts),runCheckSection("Tmux Configs",checkTmuxConfigs(),counts),runCheckSection("Worker Profiles",await checkWorkerProfiles(),counts),runCheckSection("Omni Bridge",await checkBridge(),counts),runCheckSection("Agent Config",checkLegacyAgentFrontmatter(),counts),runCheckSection("Genie Specialist",checkGenieAgentTemplate(),counts),printDoctorSummary(counts),counts.errors)process.exit(1)}function printObservabilityReport(report){if(console.log(),console.log("\x1B[1mObservability Health\x1B[0m"),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`),console.log(` partition_health: ${report.partition_health}`),console.log(` partition_count: ${report.partition_count}`),console.log(` next_rotation_at: ${report.next_rotation_at??"n/a"}`),console.log(` oldest_partition: ${report.oldest_partition??"n/a"}`),console.log(` newest_partition: ${report.newest_partition??"n/a"}`),console.log(` GENIE_WIDE_EMIT: ${report.wide_emit_flag}`),report.message)console.log(` note: ${report.message}`);console.log()}async function runObservabilityCheck(json2){let report=await collectObservabilityHealth();if(json2)console.log(JSON.stringify(report,null,2));else printObservabilityReport(report);if(report.partition_health==="fail")process.exit(1)}async function runFixTeamOrphans(opts){let{archiveOrphanTeamConfigs:archiveOrphanTeamConfigs2}=await Promise.resolve().then(() => (init_archive_orphan_team_configs(),exports_archive_orphan_team_configs)),decisions=archiveOrphanTeamConfigs2({dryRun:opts.dryRun});if(opts.json){console.log(JSON.stringify({dryRun:opts.dryRun,decisions},null,2));return}if(decisions.length===0){console.log(" no team config dirs found \u2014 nothing to do");return}for(let d of decisions){let tag=d.classification==="stale"?opts.dryRun?"WOULD ARCHIVE":"ARCHIVED":d.classification.toUpperCase(),tail=d.archivedTo?` \u2192 ${d.archivedTo}`:"";console.log(` [${tag}] ${d.team} \u2014 ${d.reason}${tail}`)}let stale=decisions.filter((d)=>d.classification==="stale").length,active=decisions.filter((d)=>d.classification==="active").length;console.log(`
|
|
910
|
+
`;if(rows.length===0)return{driftPct:null,detail:"no prior backfill row \u2014 first run will seed"};let row=rows[0];if(row.total_bytes<=0)return{driftPct:0,detail:"no JSONL bytes discovered yet"};let pct=Math.max(0,row.total_bytes-row.processed_bytes)/row.total_bytes*100,display=pct.toFixed(1);return{driftPct:pct,detail:`processed ${row.processed_bytes}/${row.total_bytes} bytes (drift ${display}%)`}}catch(err){return{driftPct:null,detail:`drift probe failed: ${err.message}`}}}async function defaultRunBackfillSync(){if(!await isAvailable())return{ranSync:!1,driftPct:null,detail:"pg unavailable \u2014 backfill skipped"};return(async()=>{try{let sql=await getConnection(),{startBackfill:startBackfill2}=await Promise.resolve().then(() => (init_session_backfill(),exports_session_backfill));await startBackfill2(sql)}catch{}})(),{ranSync:!0,driftPct:null,detail:"background convergence kicked \u2014 `genie doctor --fix` to wait"}}async function defaultRunBackfillBlocking(){if(!await isAvailable())return{ranSync:!1,driftPct:null,detail:"pg unavailable \u2014 backfill skipped"};let sql=await getConnection(),{startBackfill:startBackfill2}=await Promise.resolve().then(() => (init_session_backfill(),exports_session_backfill));await startBackfill2(sql);let after=await defaultMeasureBackfillDrift();return{ranSync:!0,driftPct:after.driftPct,detail:after.detail}}async function defaultListOrphanedZombies(){try{let{listExhaustedZombies:listExhaustedZombies2}=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry));return await listExhaustedZombies2()}catch{return[]}}function safeIsDirectory(path2){try{return statSync5(path2).isDirectory()}catch{return!1}}function summarizeInboxes(inboxesDir2){let inboxFiles=[];try{inboxFiles=readdirSync6(inboxesDir2).filter((f)=>f.endsWith(".json"))}catch{return{newestMs:null,hasContent:!1}}let newestMs=null,hasContent=!1;for(let f of inboxFiles)try{let st=statSync5(join24(inboxesDir2,f));if(newestMs===null||st.mtimeMs>newestMs)newestMs=st.mtimeMs;if(st.size>2)hasContent=!0}catch{}return{newestMs,hasContent}}function classifyTeamDir2(name,base,now){let dir=join24(base,name);if(!safeIsDirectory(dir))return null;if(existsSync19(join24(dir,"config.json")))return null;let inboxesDir2=join24(dir,"inboxes");if(!safeIsDirectory(inboxesDir2))return null;let{newestMs,hasContent}=summarizeInboxes(inboxesDir2),orphan={teamName:name,path:dir,newestInboxMs:newestMs,hasContent},active=hasContent&&newestMs!==null&&now-newestMs<ORPHAN_FRESH_WINDOW_MS;return{orphan,active}}function defaultScanTeamConfigOrphans(){let base=teamsBaseDir3(),result2={active:[],stale:[]};if(!existsSync19(base))return result2;let now=Date.now();for(let name of readdirSync6(base)){if(name.startsWith(".")||name==="_archive")continue;let classified=classifyTeamDir2(name,base,now);if(!classified)continue;(classified.active?result2.active:result2.stale).push(classified.orphan)}return result2}function defaultArchiveStaleTeamConfigs(orphans){if(orphans.length===0)return[];let archiveRoot=join24(teamsBaseDir3(),"_archive");mkdirSync9(archiveRoot,{recursive:!0});let ts3=new Date().toISOString().replace(/[:.]/g,"-"),archived=[];for(let o of orphans){let dest=join24(archiveRoot,`${o.teamName}-${ts3}`);try{renameSync4(o.path,dest),archived.push(dest)}catch{}}return archived}async function defaultRecordAudit(eventType,name,details){await recordAuditEvent("command","serve_start",eventType,"serve",{precondition:name,...details})}async function checkPartition(health,autoFix,deps){if(health.partition_health==="ok"||health.partition_health==="warn")return{name:"partition",status:"ok",detail:health.next_rotation_at?`next rotation: ${health.next_rotation_at}`:void 0};if(health.partition_health==="unknown")return{name:"partition",status:"skipped",detail:"pg unavailable \u2014 skipping partition probe"};if(!autoFix)return{name:"partition",status:"refused",detail:"today's partition is missing or rotation is overdue",fixCommand:"genie doctor --observability # then re-run; or `genie serve start` (without --no-fix)"};let result2=await deps.runPartitionMaintenance();return{name:"partition",status:"fixed",detail:`created/present ${result2.createdOrPresent}, dropped ${result2.dropped}; next rotation ${result2.nextRotationAt??"unknown"}`}}async function checkWatchdog(health,autoFix,deps){if(deps.platform!=="linux")return{name:"watchdog",status:"skipped",detail:"watchdog install is Linux/systemd only"};if(health.watchdog==="ok")return{name:"watchdog",status:"ok"};if(!autoFix)return{name:"watchdog",status:"refused",detail:health.watchdog_detail??"watchdog units missing",fixCommand:"sudo bun run packages/watchdog/src/cli.ts install"};try{let result2=await deps.installWatchdog();return{name:"watchdog",status:"fixed",detail:`wrote ${result2.filesWritten.length}, skipped ${result2.filesSkipped.length}`}}catch(err){return{name:"watchdog",status:"refused",detail:`auto-install failed: ${err.message}`,fixCommand:"sudo bun run packages/watchdog/src/cli.ts install"}}}async function checkBackfill(autoFix,deps){let drift=await deps.measureBackfillDrift();if(drift.driftPct===null)return{name:"backfill",status:"skipped",detail:drift.detail};if(drift.driftPct<BACKFILL_DRIFT_THRESHOLD_PCT)return{name:"backfill",status:"ok",detail:drift.detail};if(!autoFix)return{name:"backfill",status:"refused",detail:drift.detail,fixCommand:`genie sessions sync # drift ${drift.driftPct.toFixed(1)}% > ${BACKFILL_DRIFT_THRESHOLD_PCT}%`};return{name:"backfill",status:"fixed",detail:(await deps.runBackfillSync()).detail}}async function checkDeadPaneZombies(deps){let orphans=await deps.listOrphanedZombies();if(orphans.length===0)return{name:"dead_pane_zombies",status:"ok"};return{name:"dead_pane_zombies",status:"refused",detail:`${orphans.length} exhausted zombie(s) past TTL; visible in \`genie status\``,fixCommand:"genie prune --zombies # archive eligible rows"}}function checkTeamConfigOrphans(autoFix,deps){let scan=deps.scanTeamConfigOrphans();if(scan.active.length===0&&scan.stale.length===0)return{name:"team_config_orphans",status:"ok"};if(!autoFix){let summary=`active=${scan.active.length} stale=${scan.stale.length}`,firstActive=scan.active[0]?.teamName;return{name:"team_config_orphans",status:"refused",detail:summary,fixCommand:firstActive?`genie team repair ${firstActive} # active orphan; stale dirs archive on auto-fix`:"genie serve start # auto-fix archives stale orphans"}}let archivedPaths=deps.archiveStaleTeamConfigs(scan.stale);if(scan.active.length>0)return{name:"team_config_orphans",status:"refused",detail:`archived ${archivedPaths.length} stale; ${scan.active.length} active orphan(s) need repair`,fixCommand:`genie team repair ${scan.active[0].teamName}`};return{name:"team_config_orphans",status:"fixed",detail:`archived ${archivedPaths.length} stale orphan(s)`}}function bindDefaults(deps){return{collectHealth:deps?.collectHealth??collectObservabilityHealth,runPartitionMaintenance:deps?.runPartitionMaintenance??defaultRunPartitionMaintenance,installWatchdog:deps?.installWatchdog??defaultInstallWatchdog,runBackfillSync:deps?.runBackfillSync??defaultRunBackfillSync,measureBackfillDrift:deps?.measureBackfillDrift??defaultMeasureBackfillDrift,listOrphanedZombies:deps?.listOrphanedZombies??defaultListOrphanedZombies,scanTeamConfigOrphans:deps?.scanTeamConfigOrphans??defaultScanTeamConfigOrphans,archiveStaleTeamConfigs:deps?.archiveStaleTeamConfigs??defaultArchiveStaleTeamConfigs,platform:deps?.platform??process.platform,recordAudit:deps?.recordAudit??defaultRecordAudit,log:deps?.log??((line)=>console.log(line))}}async function ensureServeReady(opts){let deps=bindDefaults(opts.deps),health=await deps.collectHealth(),results=[];results.push(await checkPartition(health,opts.autoFix,deps)),results.push(await checkBackfill(opts.autoFix,deps)),results.push(await checkDeadPaneZombies(deps)),await emitAuditEvents(results,deps);let ok=results.every((r)=>r.status==="ok"||r.status==="fixed"||r.status==="skipped");return printReport(results,deps.log),{ok,results}}function formatDuration(ms){if(ms<1000)return`${ms}ms`;return`${(ms/1000).toFixed(1)}s`}function logMaintenanceStepStart(log,silent,label){if(!silent)log(` ${label}...`);return Date.now()}function logMaintenanceStepDone(log,silent,label,startedAt){if(!silent)log(` done ${label} (${formatDuration(Date.now()-startedAt)})`)}async function runDoctorMaintenance(opts={}){let rawRunBackfillSync=opts.deps?.runBackfillSync??defaultRunBackfillBlocking,deps=bindDefaults({...opts.deps,runBackfillSync:defaultRunBackfillBlocking,log:opts.silent?()=>{}:opts.deps?.log});deps.runBackfillSync=async()=>{let startedAt2=logMaintenanceStepStart(deps.log,opts.silent,"Running session backfill convergence (can take minutes on large transcript history)");try{return await rawRunBackfillSync()}finally{logMaintenanceStepDone(deps.log,opts.silent,"session backfill convergence",startedAt2)}};let startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Collecting observability health"),health=await deps.collectHealth();logMaintenanceStepDone(deps.log,opts.silent,"observability health",startedAt);let results=[];startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking runtime event partitions"),results.push(await checkPartition(health,!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"runtime event partitions",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking watchdog install"),results.push(await checkWatchdog(health,!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"watchdog install",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking session backfill drift"),results.push(await checkBackfill(!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"session backfill drift",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking exhausted zombie rows"),results.push(await checkDeadPaneZombies(deps)),logMaintenanceStepDone(deps.log,opts.silent,"exhausted zombie rows",startedAt),startedAt=logMaintenanceStepStart(deps.log,opts.silent,"Checking Claude team config orphans"),results.push(checkTeamConfigOrphans(!0,deps)),logMaintenanceStepDone(deps.log,opts.silent,"Claude team config orphans",startedAt),await emitAuditEvents(results,deps);let ok=results.every((r)=>r.status==="ok"||r.status==="fixed"||r.status==="skipped");return printReport(results,deps.log),{ok,results}}async function emitAuditEvents(results,deps){for(let result2 of results)if(result2.status==="fixed")await deps.recordAudit("serve.precondition.fixed",result2.name,{detail:result2.detail??null}).catch(()=>{});else if(result2.status==="refused")await deps.recordAudit("serve.precondition.refused",result2.name,{detail:result2.detail??null,fix_command:result2.fixCommand??null}).catch(()=>{})}function printReport(results,log){log(" Preconditions:");for(let r of results){let tag=statusTag(r.status),suffix=r.detail?` \u2014 ${r.detail}`:"";if(log(` ${tag} ${r.name}${suffix}`),r.status==="refused"&&r.fixCommand)log(` \u2192 ${r.fixCommand}`)}}function statusTag(status){switch(status){case"ok":return"[ok]";case"fixed":return"[fix]";case"refused":return"[!!]";case"skipped":return"[--]"}}var BACKFILL_DRIFT_THRESHOLD_PCT=5,ORPHAN_FRESH_WINDOW_MS=86400000;var init_ensure_ready=__esm(()=>{init_observability_health();init_audit();init_db()});var exports_doctor={};__export(exports_doctor,{runPostUpdateMaintenance:()=>runPostUpdateMaintenance,findBundledTmuxConfigDir:()=>findBundledTmuxConfigDir,doctorCommand:()=>doctorCommand,checkTmuxConfigs:()=>checkTmuxConfigs,checkLegacyAgentFrontmatter:()=>checkLegacyAgentFrontmatter,checkGenieAgentTemplate:()=>checkGenieAgentTemplate});import{copyFileSync as copyFileSync2,existsSync as existsSync20,mkdirSync as mkdirSync10,readFileSync as readFileSync13,readdirSync as readdirSync7,statSync as statSync6,unlinkSync as unlinkSync6,writeFileSync as writeFileSync7}from"fs";import{homedir as homedir20}from"os";import{dirname as dirname8,join as join25,resolve as resolve3}from"path";import{fileURLToPath as fileURLToPath3}from"url";var{$:$3}=globalThis.Bun;function printSectionHeader(title){console.log(),console.log(`\x1B[1m${title}:\x1B[0m`)}function printCheckResult(result2){let icon={pass:"\x1B[32m\u2713\x1B[0m",fail:"\x1B[31m\u2717\x1B[0m",warn:"\x1B[33m!\x1B[0m"}[result2.status],message=result2.message?` ${result2.message}`:"";if(console.log(` ${icon} ${result2.name}${message}`),result2.suggestion)console.log(` \x1B[2m${result2.suggestion}\x1B[0m`)}async function checkPrerequisites(){let results=[],tmuxCheck=await checkCommand("tmux");if(tmuxCheck.exists)results.push({name:"tmux",status:"pass",message:tmuxCheck.version||""});else results.push({name:"tmux",status:"fail",suggestion:"Install with: brew install tmux (or apt install tmux)"});let jqCheck=await checkCommand("jq");if(jqCheck.exists)results.push({name:"jq",status:"pass",message:jqCheck.version||""});else results.push({name:"jq",status:"fail",suggestion:"Install with: brew install jq (or apt install jq)"});let bunCheck=await checkCommand("bun");if(bunCheck.exists)results.push({name:"bun",status:"pass",message:bunCheck.version||""});else results.push({name:"bun",status:"fail",suggestion:"Install with: curl -fsSL https://bun.sh/install | bash"});let claudeCheck=await checkCommand("claude");if(claudeCheck.exists)results.push({name:"Claude Code",status:"pass",message:claudeCheck.version||""});else results.push({name:"Claude Code",status:"warn",suggestion:"Install with: npm install -g @anthropic-ai/claude-code"});let codexCheck=await checkCommand("codex");if(codexCheck.exists)results.push({name:"Codex CLI",status:"pass",message:codexCheck.version||""});else results.push({name:"Codex CLI",status:"warn",suggestion:"Install via OpenAI account; codex is optional unless using --provider codex"});let requiredForSpawn=["genie","bun","node","npm","git","claude","codex"];for(let bin of requiredForSpawn){let interactivePath=await resolveBinaryInteractive(bin),nonInteractivePath=await resolveBinaryNonInteractive(bin);if(interactivePath&&nonInteractivePath)results.push({name:`Non-interactive PATH: ${bin}`,status:"pass",message:nonInteractivePath});else if(interactivePath&&!nonInteractivePath)results.push({name:`Non-interactive PATH: ${bin}`,status:"warn",message:"interactive-only",suggestion:`Move PATH export from ~/.bashrc to ~/.profile so spawn-scripts can resolve ${bin}. (Or use a stable symlink in ~/.local/bin.)`});else if(!interactivePath&&bin!=="codex"){if(bin==="genie"||bin==="node"||bin==="npm"||bin==="git")results.push({name:`Non-interactive PATH: ${bin}`,status:"warn",message:"not in non-interactive PATH",suggestion:`Add ${bin} to ~/.profile (not just ~/.bashrc). Some flows (e.g. genie update) shell out to bare '${bin}' from non-interactive subprocesses.`})}}return results}async function resolveBinaryInteractive(bin){try{return(await $3`command -v ${bin}`.quiet().text()).trim()||null}catch{return null}}async function resolveBinaryNonInteractive(bin){try{return(await $3`sh -c "command -v ${bin}"`.quiet().text()).trim()||null}catch{return null}}async function checkConfiguration(){let results=[];if(genieConfigExists())results.push({name:"Genie config exists",status:"pass",message:contractClaudePath(getGenieConfigPath())});else results.push({name:"Genie config exists",status:"warn",message:"not found",suggestion:"Run: genie setup"});if(isSetupComplete())results.push({name:"Setup complete",status:"pass"});else results.push({name:"Setup complete",status:"warn",message:"not completed",suggestion:"Run: genie setup"});let claudeSettingsPath=getClaudeSettingsPath();if(existsSync20(claudeSettingsPath))results.push({name:"Claude settings exists",status:"pass",message:contractClaudePath(claudeSettingsPath)});else results.push({name:"Claude settings exists",status:"warn",message:"not found",suggestion:"Claude Code creates this on first run"});return results}async function checkTmux(){let results=[];try{if((await $3`${tmuxBin()} -L genie list-sessions 2>/dev/null`.quiet()).exitCode===0)results.push({name:"Server running",status:"pass"});else return results.push({name:"Server running",status:"warn",message:"no sessions",suggestion:"Start with: tmux new-session -d -s genie"}),results}catch{return results.push({name:"Server running",status:"warn",message:"could not check"}),results}let sessionName=(await loadGenieConfig()).session.name;try{if((await $3`${tmuxBin()} -L genie has-session -t ${`=${sessionName}`} 2>/dev/null`.quiet()).exitCode===0)results.push({name:`Session '${sessionName}' exists`,status:"pass"});else results.push({name:`Session '${sessionName}' exists`,status:"warn",suggestion:`Start with: tmux new-session -d -s ${sessionName}`})}catch{results.push({name:`Session '${sessionName}' exists`,status:"warn",message:"could not check"})}return results}async function checkWorkerProfiles(){let results=[];if(!genieConfigExists())return results.push({name:"Worker profiles",status:"warn",message:"no genie config",suggestion:"Run: genie setup"}),results;let config=await loadGenieConfig(),profiles=config.workerProfiles;if(!profiles||Object.keys(profiles).length===0)return results.push({name:"Worker profiles",status:"pass",message:"none configured (using defaults)"}),results;let totalProfiles=Object.keys(profiles).length;results.push({name:"Profiles configured",status:"pass",message:`${totalProfiles} profile${totalProfiles===1?"":"s"}`});for(let name of Object.keys(profiles))results.push({name:`Profile '${name}'`,status:"pass",message:"claude (direct)"});if(config.defaultWorkerProfile)if(profiles[config.defaultWorkerProfile])results.push({name:"Default profile",status:"pass",message:config.defaultWorkerProfile});else results.push({name:"Default profile",status:"warn",message:`'${config.defaultWorkerProfile}' not found`,suggestion:"Run: genie profiles default <profile>"});return results}async function checkBridge(){let results=[];try{let{getBridgeStatus:getBridgeStatus2,removeBridgePidfile:removeBridgePidfile2}=await Promise.resolve().then(() => (init_bridge_status(),exports_bridge_status)),res=await getBridgeStatus2(void 0,{});if(res.state==="stopped")return results.push({name:"Bridge",status:"warn",message:"stopped (no pidfile)",suggestion:"Start the bridge with: genie serve"}),results;if(res.state==="stale"){if(res.pidfile)removeBridgePidfile2();return results.push({name:"Bridge",status:"fail",message:`stale: ${res.detail}`,suggestion:"Restart the bridge with: genie serve restart"}),results}let{pong,pidfile}=res;if(!pong||!pidfile)return results.push({name:"Bridge",status:"warn",message:"running state missing pong/pidfile metadata"}),results;let uptimeSec=Math.round(pong.uptimeMs/1000);results.push({name:"Bridge running",status:"pass",message:`running (pid ${pong.pid}, uptime ${uptimeSec}s)`}),results.push({name:"NATS ping",status:"pass",message:`pong in ${res.latencyMs??0}ms (${pidfile.natsUrl})`}),results.push({name:"Subjects",status:"pass",message:pong.subjects.join(", ")})}catch(err){let detail=err instanceof Error?err.message:String(err);results.push({name:"Bridge module",status:"warn",message:`could not probe bridge: ${detail}`})}return results}function checkGenieAgentTemplate(workspaceRoot){let root=workspaceRoot??findWorkspace()?.root;if(!root)return[];let genieDir=join25(root,"agents","genie");if(!existsSync20(genieDir))return[];let agentsMd=join25(genieDir,"AGENTS.md"),agentYaml=join25(genieDir,"agent.yaml"),issues=[];if(existsSync20(agentsMd))try{if(readFileSync13(agentsMd,"utf-8").includes(STALE_GENIE_AGENTS_MD_MARKER))issues.push("AGENTS.md uses generic placeholder template")}catch{}if(existsSync20(agentYaml))try{let text=readFileSync13(agentYaml,"utf-8");if(!STALE_GENIE_AGENT_YAML_MISSING_MODEL_REGEX.test(text))issues.push("agent.yaml missing model field (TUI falls back to gray)")}catch{}if(issues.length===0)return[{name:"agents/genie scaffold up to date",status:"pass"}];return[{name:"agents/genie stale scaffold",status:"warn",message:issues.join("; "),suggestion:"Run: genie doctor --fix (re-emits genie specialist templates, preserves user edits)"}]}function findBundledTmuxConfigDir(){try{let moduleDir=dirname8(fileURLToPath3(import.meta.url));for(let i2=0;i2<6;i2+=1){let candidate=resolve3(moduleDir,"../".repeat(i2+1),"scripts","tmux");if(existsSync20(join25(candidate,"tui-tmux.conf"))&&existsSync20(join25(candidate,"genie.tmux.conf")))return candidate}}catch{}return null}function checkTmuxConfigs(){if(!findBundledTmuxConfigDir())return[{name:"tmux configs",status:"pass",message:"bundled configs unavailable (skipped)"}];let home=join25(homedir20(),".genie"),stale=[],expectedSnippet="unbind -n MouseDown3Pane";for(let file of["tui-tmux.conf","tmux.conf"]){let installedPath=join25(home,file);if(!existsSync20(installedPath))continue;try{if(!readFileSync13(installedPath,"utf-8").includes(expectedSnippet))stale.push(file)}catch{stale.push(file)}}if(stale.length===0)return[{name:"~/.genie tmux configs up to date",status:"pass"}];return[{name:"~/.genie tmux configs stale",status:"warn",message:`missing right-click unbind in: ${stale.join(", ")}`,suggestion:"Run: genie doctor --fix (refreshes ~/.genie tmux configs from bundled scripts/tmux/)"}]}function isAgentDirectory(path2){try{return statSync6(path2).isDirectory()}catch{return!1}}function hasLegacyFrontmatter(agentDir){let yamlPath=join25(agentDir,"agent.yaml"),agentsMdPath=join25(agentDir,"AGENTS.md");if(!existsSync20(yamlPath)||!existsSync20(agentsMdPath))return!1;try{return readFileSync13(agentsMdPath,"utf-8").slice(0,4).startsWith("---")}catch{return!1}}function checkLegacyAgentFrontmatter(workspaceRoot){let results=[],root=workspaceRoot??findWorkspace()?.root;if(!root)return[];let agentsDir=join25(root,"agents");if(!existsSync20(agentsDir))return[];let entries;try{entries=readdirSync7(agentsDir)}catch{return[]}for(let name of entries){let agentDir=join25(agentsDir,name);if(!isAgentDirectory(agentDir))continue;if(!hasLegacyFrontmatter(agentDir))continue;results.push({name:`agents/${name}/AGENTS.md`,status:"warn",message:"legacy frontmatter detected (ignored by sync)",suggestion:`Move config into agents/${name}/agent.yaml \u2014 AGENTS.md is prompt-only post-migration.`})}if(results.length===0)results.push({name:"No legacy frontmatter in agents/*/AGENTS.md",status:"pass"});return results}function runCheckSection(label,results,counts){printSectionHeader(label);for(let result2 of results){if(printCheckResult(result2),result2.status==="fail")counts.errors=!0;if(result2.status==="warn")counts.warnings=!0}}async function doctorCommand(options){if(options?.fix){await doctorFix();return}if(options?.fixTeamOrphans){await runFixTeamOrphans({dryRun:Boolean(options.dryRun),json:Boolean(options.json)});return}if(options?.observability){await runObservabilityCheck(Boolean(options.json));return}if(options?.perf){let{runPerfCheck:runPerfCheck2}=await Promise.resolve().then(() => (init_perf_check(),exports_perf_check));await runPerfCheck2(Boolean(options.json));return}console.log(),console.log("\x1B[1mGenie Doctor\x1B[0m"),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`);let counts={errors:!1,warnings:!1};if(runCheckSection("Prerequisites",await checkPrerequisites(),counts),runCheckSection("Installer Resolution",await collectInstallerResolution(),counts),runCheckSection("Configuration",await checkConfiguration(),counts),runCheckSection("Tmux",await checkTmux(),counts),runCheckSection("Tmux Configs",checkTmuxConfigs(),counts),runCheckSection("Worker Profiles",await checkWorkerProfiles(),counts),runCheckSection("Omni Bridge",await checkBridge(),counts),runCheckSection("Agent Config",checkLegacyAgentFrontmatter(),counts),runCheckSection("Genie Specialist",checkGenieAgentTemplate(),counts),printDoctorSummary(counts),counts.errors)process.exit(1)}function printObservabilityReport(report){if(console.log(),console.log("\x1B[1mObservability Health\x1B[0m"),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`),console.log(` partition_health: ${report.partition_health}`),console.log(` partition_count: ${report.partition_count}`),console.log(` next_rotation_at: ${report.next_rotation_at??"n/a"}`),console.log(` oldest_partition: ${report.oldest_partition??"n/a"}`),console.log(` newest_partition: ${report.newest_partition??"n/a"}`),console.log(` GENIE_WIDE_EMIT: ${report.wide_emit_flag}`),report.message)console.log(` note: ${report.message}`);console.log()}async function runObservabilityCheck(json2){let report=await collectObservabilityHealth();if(json2)console.log(JSON.stringify(report,null,2));else printObservabilityReport(report);if(report.partition_health==="fail")process.exit(1)}async function runFixTeamOrphans(opts){let{archiveOrphanTeamConfigs:archiveOrphanTeamConfigs2}=await Promise.resolve().then(() => (init_archive_orphan_team_configs(),exports_archive_orphan_team_configs)),decisions=archiveOrphanTeamConfigs2({dryRun:opts.dryRun});if(opts.json){console.log(JSON.stringify({dryRun:opts.dryRun,decisions},null,2));return}if(decisions.length===0){console.log(" no team config dirs found \u2014 nothing to do");return}for(let d of decisions){let tag=d.classification==="stale"?opts.dryRun?"WOULD ARCHIVE":"ARCHIVED":d.classification.toUpperCase(),tail=d.archivedTo?` \u2192 ${d.archivedTo}`:"";console.log(` [${tag}] ${d.team} \u2014 ${d.reason}${tail}`)}let stale=decisions.filter((d)=>d.classification==="stale").length,active=decisions.filter((d)=>d.classification==="active").length;console.log(`
|
|
911
911
|
${decisions.length} dirs inspected, ${stale} archived, ${active} flagged active.`)}function printDoctorSummary(counts){if(console.log(),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m`),counts.errors)console.log("\x1B[31mSome checks failed.\x1B[0m Run \x1B[36mgenie setup\x1B[0m to fix.");else if(counts.warnings)console.log("\x1B[33mSome warnings detected.\x1B[0m Everything should still work.");else console.log("\x1B[32mAll checks passed!\x1B[0m");console.log()}function legacyPgserveRepairEnabled(){return process.env.GENIE_PG_FORCE_TCP==="1"||process.env.GENIE_DOCTOR_FIX_LEGACY_PGSERVE==="1"}async function killStalePostgres(genieHome3){if(!legacyPgserveRepairEnabled()){console.log(" Skipping legacy pgserve v1 process cleanup (v1/v2 coexistence)");return}console.log(" Killing stale Genie legacy pgserve processes...");try{let{execSync:execSync4}=await import("child_process"),escaped=join25(genieHome3,"data","pgserve").replace(/\//g,"\\/");execSync4(`pkill -9 -f "postgres.*${escaped}" 2>/dev/null || true`,{stdio:"ignore",timeout:5000}),execSync4(`pkill -9 -f "pgserve.*${escaped}" 2>/dev/null || true`,{stdio:"ignore",timeout:5000}),console.log(" \x1B[32m\u2713\x1B[0m Stale Genie legacy pgserve processes killed")}catch{console.log(" \x1B[33m!\x1B[0m Could not kill stale Genie legacy pgserve processes")}}async function cleanSharedMemory(){console.log(" Cleaning shared memory...");try{let{execSync:execSync4}=await import("child_process");if(process.platform==="darwin")execSync4("ipcs -m 2>/dev/null | awk '/^m/ {print $2}' | xargs -I{} ipcrm -m {} 2>/dev/null || true",{stdio:"ignore",timeout:5000});else execSync4("ipcs -m 2>/dev/null | awk '$6 == 0 {print $2}' | xargs -I{} ipcrm -m {} 2>/dev/null || true",{stdio:"ignore",timeout:5000});console.log(" \x1B[32m\u2713\x1B[0m Shared memory cleaned")}catch{console.log(" \x1B[32m\u2713\x1B[0m No stale shared memory")}}async function stopExistingDaemon(pidFile){try{let{readFileSync:readFileSync14}=await import("fs"),pid=Number.parseInt(readFileSync14(pidFile,"utf-8").trim(),10);if(!Number.isNaN(pid)&&pid>0)try{process.kill(pid,"SIGTERM"),console.log(` \x1B[32m\u2713\x1B[0m Stopped existing daemon (PID ${pid})`),await new Promise((r)=>setTimeout(r,1000))}catch{}}catch{}}function removeStaleFiles(genieHome3,pidFile){let files=[pidFile];if(legacyPgserveRepairEnabled())files.push(join25(genieHome3,"pgserve.port"),join25(genieHome3,"data","pgserve","postmaster.pid"));else console.log(" Leaving legacy pgserve v1 port/data files untouched (v1/v2 coexistence)");for(let file of files)if(existsSync20(file))try{unlinkSync6(file),console.log(` \x1B[32m\u2713\x1B[0m Removed ${file}`)}catch{console.log(` \x1B[33m!\x1B[0m Could not remove ${file}`)}}async function restartDaemon(){console.log(" Restarting daemon...");try{let{spawn:spawn2}=await import("child_process"),bunPath=process.execPath??"bun",genieBin=process.argv[1]??"genie";spawn2(bunPath,[genieBin,"daemon","start"],{detached:!0,stdio:"ignore"}).unref(),await new Promise((resolve4)=>setTimeout(resolve4,2000)),console.log(" \x1B[32m\u2713\x1B[0m Daemon restart initiated")}catch{console.log(" \x1B[33m!\x1B[0m Could not restart daemon \u2014 run: genie daemon start")}}function isAgentsMdUserEdited(target,fresh){if(!existsSync20(target))return!1;try{let current=readFileSync13(target,"utf-8");if(current.trim().length===0)return!1;if(current.includes(STALE_GENIE_AGENTS_MD_MARKER))return!1;return current!==fresh}catch{return!1}}function writeGenieTemplate(targetDir,name,content){let target=join25(targetDir,name),userEdited=name==="AGENTS.md"&&isAgentsMdUserEdited(target,content),writeTo=userEdited?`${target}.new`:target;try{writeFileSync7(writeTo,content);let marker=userEdited?`wrote ${name}.new (user edits preserved \u2014 merge manually)`:`wrote ${name}`;console.log(` \x1B[32m\u2713\x1B[0m ${marker}`)}catch(err){let detail=err instanceof Error?err.message:String(err);console.log(` \x1B[31m\u2717\x1B[0m ${name}: ${detail}`)}}function fixGenieAgentTemplate(workspaceRoot){let root=workspaceRoot??findWorkspace()?.root;if(!root){console.log(" \x1B[33m!\x1B[0m No workspace detected \u2014 skipping genie-template repair");return}let genieDir=join25(root,"agents","genie");if(!existsSync20(genieDir)){console.log(" \x1B[2m\xB7\x1B[0m No agents/genie directory \u2014 skipping");return}console.log(" Refreshing agents/genie scaffold..."),writeGenieTemplate(genieDir,"AGENTS.md",GENIE_AGENTS_TEMPLATE),writeGenieTemplate(genieDir,"SOUL.md",GENIE_SOUL_TEMPLATE),writeGenieTemplate(genieDir,"HEARTBEAT.md",GENIE_HEARTBEAT_TEMPLATE)}function ensureGenieHomeDir(home){if(existsSync20(home))return!0;try{return mkdirSync10(home,{recursive:!0}),!0}catch{return console.log(` \x1B[31m\u2717\x1B[0m Could not create ${home}`),!1}}function refreshTmuxConfFile(bundledDir,home,srcFile,dstFile){let src=join25(bundledDir,srcFile),dst=join25(home,dstFile);if(!existsSync20(src))return;if(existsSync20(dst))try{copyFileSync2(dst,`${dst}.bak`)}catch{}try{copyFileSync2(src,dst),console.log(` \x1B[32m\u2713\x1B[0m wrote ${dstFile} (previous saved as ${dstFile}.bak)`)}catch(err){let detail=err instanceof Error?err.message:String(err);console.log(` \x1B[31m\u2717\x1B[0m ${dstFile}: ${detail}`)}}function fixTmuxConfigs(){let bundledDir=findBundledTmuxConfigDir();if(!bundledDir){console.log(" \x1B[33m!\x1B[0m Bundled tmux configs not found \u2014 skipping");return}let home=join25(homedir20(),".genie");if(!ensureGenieHomeDir(home))return;console.log(" Refreshing ~/.genie tmux configs..."),refreshTmuxConfFile(bundledDir,home,"tui-tmux.conf","tui-tmux.conf"),refreshTmuxConfFile(bundledDir,home,"genie.tmux.conf","tmux.conf")}async function runMaintenancePreconditions(silent=!1,log){try{let{runDoctorMaintenance:runDoctorMaintenance2}=await Promise.resolve().then(() => (init_ensure_ready(),exports_ensure_ready));await runDoctorMaintenance2({silent,deps:log?{log}:void 0})}catch(err){let msg=err instanceof Error?err.message:String(err);if(!silent)console.warn(` Maintenance preconditions skipped: ${msg}`)}}async function doctorFix(){console.log(`
|
|
912
912
|
\x1B[1mGenie Doctor \u2014 Auto Fix\x1B[0m`),console.log(`\x1B[2m${"\u2500".repeat(40)}\x1B[0m
|
|
913
913
|
`);let genieHome3=process.env.GENIE_HOME??join25(homedir20(),".genie");await killStalePostgres(genieHome3),await cleanSharedMemory();let pidFile=join25(genieHome3,"scheduler.pid");await stopExistingDaemon(pidFile),removeStaleFiles(genieHome3,pidFile),fixGenieAgentTemplate(),fixTmuxConfigs(),await runMaintenancePreconditions(),await restartDaemon(),console.log(`
|
|
@@ -1034,7 +1034,7 @@ Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.
|
|
|
1034
1034
|
`:"";return writeFileSync10(filePath,newContent),!0}async function promptUninstallFrom(filePath,marker,label){if(!existsSync22(filePath))return;if(!contentExists(filePath,marker)){console.log(`\u2713 ${label} has no genie shortcuts`);return}if(await prompt(`Remove shortcuts from ${filePath}? [Y/n] `)==="n"){console.log(`\u23ED\uFE0F Skipped ${label}`);return}if(removeMarkedContent(filePath,marker))console.log(`\u2705 Removed from ${filePath}`)}async function uninstallShortcuts(){let home=homedir22(),marker="generated by genie-cli";console.log(`Uninstalling Warp-like shortcuts...
|
|
1035
1035
|
`),await promptUninstallFrom(join27(home,".tmux.conf"),"generated by genie-cli","tmux.conf");for(let shellRc of[join27(home,".zshrc"),join27(home,".bashrc")])await promptUninstallFrom(shellRc,"generated by genie-cli",shellRc);let termuxDir=join27(home,".termux"),isTermux=existsSync22(termuxDir)||process.env.TERMUX_VERSION;if(isTermux){let termuxProps=join27(termuxDir,"termux.properties");if(await promptUninstallFrom(termuxProps,"generated by genie-cli","termux.properties"),!contentExists(termuxProps,"generated by genie-cli"))console.log(" Run: termux-reload-settings")}if(console.log(`
|
|
1036
1036
|
\u2705 Uninstallation complete!`),console.log(`
|
|
1037
|
-
Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.log(" 2. Restart your shell or run: source ~/.bashrc"),isTermux)console.log(" 3. Reload Termux: termux-reload-settings")}var GENIE_CONTENT_MARKERS;var init_shortcuts=__esm(()=>{GENIE_CONTENT_MARKERS=["genie","Ctrl+","split-window","new-window","stty -ixon","Warp-like","bind-key -n","extra-keys","F1=","bind -x"]});var exports_setup={};__export(exports_setup,{setupCommand:()=>setupCommand});import{homedir as homedir23}from"os";import{join as join28}from"path";function printHeader(){console.log(),console.log(`\x1B[1m\x1B[36m${"=".repeat(64)}\x1B[0m`),console.log("\x1B[1m\x1B[36m Genie Setup Wizard\x1B[0m"),console.log(`\x1B[1m\x1B[36m${"=".repeat(64)}\x1B[0m`),console.log()}function printSection(title,description){if(console.log(),console.log(`\x1B[1m${title}\x1B[0m`),description)console.log(`\x1B[2m${description}\x1B[0m`);console.log()}async function configureSession(config,quick){if(printSection("2. Session Configuration","Configure tmux session settings"),quick)return console.log(` Using defaults: session="${config.session.name}", window="${config.session.defaultWindow}"`),config;let sessionName=await esm_default5({message:"Session name:",default:config.session.name}),defaultWindow=await esm_default5({message:"Default window name:",default:config.session.defaultWindow}),autoCreate=await esm_default4({message:"Auto-create session on connect?",default:config.session.autoCreate});return config.session={name:sessionName,defaultWindow,autoCreate},config}async function configureTerminal(config,quick){if(printSection("3. Terminal Defaults","Configure default values for term commands"),quick)return console.log(` Using defaults: timeout=${config.terminal.execTimeout}ms, lines=${config.terminal.readLines}`),config;let timeoutStr=await esm_default5({message:"Exec timeout (milliseconds):",default:String(config.terminal.execTimeout),validate:(v)=>{let n=Number.parseInt(v,10);return!Number.isNaN(n)&&n>0?!0:"Must be a positive number"}}),linesStr=await esm_default5({message:"Read lines (default for genie agent read):",default:String(config.terminal.readLines),validate:(v)=>{let n=Number.parseInt(v,10);return!Number.isNaN(n)&&n>0?!0:"Must be a positive number"}}),worktreeBase=await esm_default5({message:"Worktree base directory (leave empty for ~/.genie/worktrees/<project>/):",default:config.terminal.worktreeBase??""});return config.terminal={execTimeout:Number.parseInt(timeoutStr,10),readLines:Number.parseInt(linesStr,10),...worktreeBase?{worktreeBase}:{}},config}async function configureShortcuts(config,quick){printSection("4. Keyboard Shortcuts","Warp-like tmux shortcuts for quick navigation");let home=homedir23(),tmuxConf=join28(home,".tmux.conf");if(isShortcutsInstalled(tmuxConf))return console.log(" \x1B[32m\u2713\x1B[0m Tmux shortcuts already installed"),config.shortcuts.tmuxInstalled=!0,config;if(console.log(" Available shortcuts:"),console.log(" \x1B[36mCtrl+T\x1B[0m \u2192 New tab (window)"),console.log(" \x1B[36mCtrl+S\x1B[0m \u2192 Vertical split"),console.log(" \x1B[36mCtrl+H\x1B[0m \u2192 Horizontal split"),console.log(),quick)return console.log(" Skipped in quick mode. Run \x1B[36mgenie setup --shortcuts\x1B[0m to install."),config;if(await esm_default4({message:"Install tmux keyboard shortcuts?",default:!1}))console.log(),await installShortcuts(),config.shortcuts.tmuxInstalled=!0,await updateShortcutsConfig({tmuxInstalled:!0});else console.log(" Skipped. Run \x1B[36mgenie shortcuts install\x1B[0m later.");return config}function printCodexResult(result2){if(result2==="changed")console.log(" \x1B[32m\u2713\x1B[0m Codex config updated");else if(result2==="unchanged")console.log(" \x1B[32m\u2713\x1B[0m Codex config already up to date");else console.log(" \x1B[31m\u2717\x1B[0m Failed to update codex config")}async function configureCodex(config,quick){printSection("5. Codex Integration","Configure OpenAI Codex for genie agents");let codexCheck=await checkCommand("codex");if(!codexCheck.exists)return console.log(" \x1B[33m!\x1B[0m Codex CLI not found. Skipping codex integration."),config;if(console.log(` \x1B[32m\u2713\x1B[0m Codex CLI found (${codexCheck.version??"unknown version"})`),isCodexConfigured())return console.log(" \x1B[32m\u2713\x1B[0m Codex config already configured"),config.codex={configured:!0},config;if(console.log(),console.log(" Genie needs to configure codex for agent communication:"),console.log(" \x1B[36mdisable_paste_burst\x1B[0m \u2192 Reliable tmux command injection"),console.log(" \x1B[36mOTel exporter\x1B[0m \u2192 Telemetry relay for state detection"),console.log(` Config: \x1B[2m${contractPath(getCodexConfigPath())}\x1B[0m`),console.log(),quick){let result2=ensureCodexOtelConfig();return printCodexResult(result2),config.codex={configured:result2!=="error"},config}if(await esm_default4({message:"Configure Codex for genie agent integration?",default:!0})){let result2=ensureCodexOtelConfig();printCodexResult(result2),config.codex={configured:result2!=="error"}}else console.log(" Skipped. Run \x1B[36mgenie setup --codex\x1B[0m later.");return config}async function configureDebug(config,quick){if(printSection("6. Debug Options","Logging and debugging settings"),quick)return console.log(" Using defaults: tmuxDebug=false, verbose=false"),config;let tmuxDebug=await esm_default4({message:"Enable tmux debug logging?",default:config.logging.tmuxDebug}),verbose=await esm_default4({message:"Enable verbose mode?",default:config.logging.verbose});return config.logging={tmuxDebug,verbose},config}async function configurePromptMode(config,quick){if(printSection("7. Prompt Mode","Controls how genie injects system prompts into Claude Code"),quick)return console.log(` Using default: promptMode="${config.promptMode}"`),config;console.log(" append \u2014 Uses --append-system-prompt-file (preserves Claude Code default system prompt)"),console.log(" system \u2014 Uses --system-prompt-file (replaces Claude Code default system prompt)"),console.log();let promptMode=await esm_default11({message:"Prompt mode:",choices:[{name:"append (recommended \u2014 preserves CC default)",value:"append"},{name:"system (replaces CC default)",value:"system"}],default:config.promptMode});return config.promptMode=promptMode,config}async function showSummaryAndSave(config){printSection("Summary",`Configuration will be saved to ${contractPath(getGenieConfigPath())}`),console.log(` Session: \x1B[36m${config.session.name}\x1B[0m (window: ${config.session.defaultWindow})`),console.log(` Terminal: timeout=${config.terminal.execTimeout}ms, lines=${config.terminal.readLines}`),console.log(` Shortcuts: ${config.shortcuts.tmuxInstalled?"\x1B[32minstalled\x1B[0m":"\x1B[2mnot installed\x1B[0m"}`),console.log(` Codex: ${config.codex?.configured?"\x1B[32mconfigured\x1B[0m":"\x1B[2mnot configured\x1B[0m"}`),console.log(` Debug: tmux=${config.logging.tmuxDebug}, verbose=${config.logging.verbose}`),console.log(` Prompt mode: \x1B[36m${config.promptMode}\x1B[0m`),console.log(),config.setupComplete=!0,config.lastSetupAt=new Date().toISOString(),await saveGenieConfig(config),console.log("\x1B[32m\u2713 Configuration saved!\x1B[0m")}async function showCurrentConfig(){let config=await loadGenieConfig();console.log(),console.log("\x1B[1mCurrent Genie Configuration\x1B[0m"),console.log(`\x1B[2m${contractPath(getGenieConfigPath())}\x1B[0m`),console.log(),console.log(JSON.stringify(config,null,2)),console.log()}function printNextSteps(){console.log(),console.log("\x1B[1mNext Steps:\x1B[0m"),console.log(),console.log(" Start a session: \x1B[36mgenie\x1B[0m"),console.log(" Watch AI work: \x1B[36mtmux attach -t genie\x1B[0m"),console.log(" Check health: \x1B[36mgenie doctor\x1B[0m"),console.log()}async function setupCommand(options={}){if(options.show){await showCurrentConfig();return}if(options.reset){await resetConfig(),console.log("\x1B[32m\u2713 Configuration reset to defaults.\x1B[0m"),console.log();return}let config=await loadGenieConfig();if(options.shortcuts){printHeader(),await configureShortcuts(config,!1),await markSetupComplete();return}if(options.terminal){printHeader(),config=await configureTerminal(config,!1),await saveGenieConfig(config),console.log("\x1B[32m\u2713 Terminal configuration saved.\x1B[0m");return}if(options.session){printHeader(),config=await configureSession(config,!1),await saveGenieConfig(config),console.log("\x1B[32m\u2713 Session configuration saved.\x1B[0m");return}if(options.codex){if(printHeader(),config=await configureCodex(config,!1),await saveGenieConfig(config),config.codex?.configured)console.log("\x1B[32m\u2713 Codex configuration saved.\x1B[0m");return}let quick=options.quick??!1;if(printHeader(),quick)console.log("\x1B[2mQuick mode: accepting all defaults\x1B[0m");config=await configureSession(config,quick),config=await configureTerminal(config,quick),config=await configureShortcuts(config,quick),config=await configureCodex(config,quick),config=await configureDebug(config,quick),config=await configurePromptMode(config,quick),await showSummaryAndSave(config),installGenieTmuxConf(),printNextSteps()}function installGenieTmuxConf(){let{existsSync:existsSync23,copyFileSync:copyFileSync3,mkdirSync:mkdirSync13,chmodSync:chmodSync2}=__require("fs"),{resolve:resolve4,dirname:dirname8}=__require("path"),genieHome3=process.env.GENIE_HOME??join28(homedir23(),".genie"),dest=join28(genieHome3,"tmux.conf");if(existsSync23(dest))return;let src=[resolve4(__dirname,"..","..","scripts","tmux","genie.tmux.conf"),resolve4(__dirname,"..","scripts","tmux","genie.tmux.conf")].find((p)=>existsSync23(p));if(!src)return;try{mkdirSync13(genieHome3,{recursive:!0}),copyFileSync3(src,dest),console.log(`\x1B[32m\u2713\x1B[0m Installed genie tmux config to ${dest}`)}catch{}let osc52Src=join28(dirname8(src),"osc52-copy.sh"),osc52Dest=join28(genieHome3,"osc52-copy.sh");if(existsSync23(osc52Src))try{copyFileSync3(osc52Src,osc52Dest),chmodSync2(osc52Dest,493)}catch{}}var __dirname="/home/runner/_work/genie/genie/src/genie-commands";var init_setup=__esm(()=>{init_esm14();init_codex_config();init_genie_config2();init_system_detect();init_shortcuts()});var exports_version={};__export(exports_version,{VERSION:()=>VERSION});import{existsSync as existsSync26,readFileSync as readFileSync18}from"fs";import{dirname as dirname8,resolve as resolve4}from"path";function readPackageJson(path3){try{if(!existsSync26(path3))return null;return JSON.parse(readFileSync18(path3,"utf-8"))}catch{return null}}function readVersionFromPackageJson(){let startDir=dirname8(import.meta.dir??__dirname),current=startDir;for(let depth=0;depth<MAX_WALK_DEPTH;depth++){let candidate=resolve4(current,"package.json"),pkg=readPackageJson(candidate);if(pkg?.name===PACKAGE_NAME&&pkg.version)return pkg.version;let parent=dirname8(current);if(parent===current)break;current=parent}current=startDir;for(let depth=0;depth<MAX_WALK_DEPTH;depth++){let candidate=resolve4(current,"package.json"),pkg=readPackageJson(candidate);if(pkg?.version)return pkg.version;let parent=dirname8(current);if(parent===current)break;current=parent}return FALLBACK_VERSION}var __dirname="/home/runner/_work/genie/genie/src/lib",FALLBACK_VERSION="0.0.0-unknown",PACKAGE_NAME="@automagik/genie",MAX_WALK_DEPTH=10,VERSION;var init_version=__esm(()=>{VERSION=readVersionFromPackageJson()});import{execSync as execSync5}from"child_process";function getRecentGitHistory(filePath,cwd){try{let trimmed=execSync5(`git log --oneline -n ${MAX_COMMITS} -- ${JSON.stringify(filePath)}`,{encoding:"utf-8",timeout:5000,cwd,stdio:["pipe","pipe","pipe"]}).trim();if(!trimmed)return null;return trimmed}catch{return null}}async function auditContext(payload){let input=payload.tool_input;if(!input)return;let filePath=input.file_path;if(!filePath)return;let cwd=payload.cwd??process.cwd(),history=getRecentGitHistory(filePath,cwd);if(!history)return;return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:`[audit-context] Recent git history for ${filePath}:
|
|
1037
|
+
Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.log(" 2. Restart your shell or run: source ~/.bashrc"),isTermux)console.log(" 3. Reload Termux: termux-reload-settings")}var GENIE_CONTENT_MARKERS;var init_shortcuts=__esm(()=>{GENIE_CONTENT_MARKERS=["genie","Ctrl+","split-window","new-window","stty -ixon","Warp-like","bind-key -n","extra-keys","F1=","bind -x"]});var exports_setup={};__export(exports_setup,{setupCommand:()=>setupCommand});import{homedir as homedir23}from"os";import{join as join28}from"path";function printHeader(){console.log(),console.log(`\x1B[1m\x1B[36m${"=".repeat(64)}\x1B[0m`),console.log("\x1B[1m\x1B[36m Genie Setup Wizard\x1B[0m"),console.log(`\x1B[1m\x1B[36m${"=".repeat(64)}\x1B[0m`),console.log()}function printSection(title,description){if(console.log(),console.log(`\x1B[1m${title}\x1B[0m`),description)console.log(`\x1B[2m${description}\x1B[0m`);console.log()}async function configureSession(config,quick){if(printSection("2. Session Configuration","Configure tmux session settings"),quick)return console.log(` Using defaults: session="${config.session.name}", window="${config.session.defaultWindow}"`),config;let sessionName=await esm_default5({message:"Session name:",default:config.session.name}),defaultWindow=await esm_default5({message:"Default window name:",default:config.session.defaultWindow}),autoCreate=await esm_default4({message:"Auto-create session on connect?",default:config.session.autoCreate});return config.session={name:sessionName,defaultWindow,autoCreate},config}async function configureTerminal(config,quick){if(printSection("3. Terminal Defaults","Configure default values for term commands"),quick)return console.log(` Using defaults: timeout=${config.terminal.execTimeout}ms, lines=${config.terminal.readLines}`),config;let timeoutStr=await esm_default5({message:"Exec timeout (milliseconds):",default:String(config.terminal.execTimeout),validate:(v)=>{let n=Number.parseInt(v,10);return!Number.isNaN(n)&&n>0?!0:"Must be a positive number"}}),linesStr=await esm_default5({message:"Read lines (default for genie agent read):",default:String(config.terminal.readLines),validate:(v)=>{let n=Number.parseInt(v,10);return!Number.isNaN(n)&&n>0?!0:"Must be a positive number"}}),worktreeBase=await esm_default5({message:"Worktree base directory (leave empty for ~/.genie/worktrees/<project>/):",default:config.terminal.worktreeBase??""});return config.terminal={execTimeout:Number.parseInt(timeoutStr,10),readLines:Number.parseInt(linesStr,10),...worktreeBase?{worktreeBase}:{}},config}async function configureShortcuts(config,quick){printSection("4. Keyboard Shortcuts","Warp-like tmux shortcuts for quick navigation");let home=homedir23(),tmuxConf=join28(home,".tmux.conf");if(isShortcutsInstalled(tmuxConf))return console.log(" \x1B[32m\u2713\x1B[0m Tmux shortcuts already installed"),config.shortcuts.tmuxInstalled=!0,config;if(console.log(" Available shortcuts:"),console.log(" \x1B[36mCtrl+T\x1B[0m \u2192 New tab (window)"),console.log(" \x1B[36mCtrl+S\x1B[0m \u2192 Vertical split"),console.log(" \x1B[36mCtrl+H\x1B[0m \u2192 Horizontal split"),console.log(),quick)return console.log(" Skipped in quick mode. Run \x1B[36mgenie setup --shortcuts\x1B[0m to install."),config;if(await esm_default4({message:"Install tmux keyboard shortcuts?",default:!1}))console.log(),await installShortcuts(),config.shortcuts.tmuxInstalled=!0,await updateShortcutsConfig({tmuxInstalled:!0});else console.log(" Skipped. Run \x1B[36mgenie shortcuts install\x1B[0m later.");return config}function printCodexResult(result2){if(result2==="changed")console.log(" \x1B[32m\u2713\x1B[0m Codex config updated");else if(result2==="unchanged")console.log(" \x1B[32m\u2713\x1B[0m Codex config already up to date");else console.log(" \x1B[31m\u2717\x1B[0m Failed to update codex config")}async function configureCodex(config,quick){printSection("5. Codex Integration","Configure OpenAI Codex for genie agents");let codexCheck=await checkCommand("codex");if(!codexCheck.exists)return console.log(" \x1B[33m!\x1B[0m Codex CLI not found. Skipping codex integration."),config;if(console.log(` \x1B[32m\u2713\x1B[0m Codex CLI found (${codexCheck.version??"unknown version"})`),isCodexConfigured())return console.log(" \x1B[32m\u2713\x1B[0m Codex config already configured"),config.codex={configured:!0},config;if(console.log(),console.log(" Genie needs to configure codex for agent communication:"),console.log(" \x1B[36mdisable_paste_burst\x1B[0m \u2192 Reliable tmux command injection"),console.log(" \x1B[36mOTel exporter\x1B[0m \u2192 Telemetry relay for state detection"),console.log(` Config: \x1B[2m${contractPath(getCodexConfigPath())}\x1B[0m`),console.log(),quick){let result2=ensureCodexOtelConfig();return printCodexResult(result2),config.codex={configured:result2!=="error"},config}if(await esm_default4({message:"Configure Codex for genie agent integration?",default:!0})){let result2=ensureCodexOtelConfig();printCodexResult(result2),config.codex={configured:result2!=="error"}}else console.log(" Skipped. Run \x1B[36mgenie setup --codex\x1B[0m later.");return config}async function configureDebug(config,quick){if(printSection("6. Debug Options","Logging and debugging settings"),quick)return console.log(" Using defaults: tmuxDebug=false, verbose=false"),config;let tmuxDebug=await esm_default4({message:"Enable tmux debug logging?",default:config.logging.tmuxDebug}),verbose=await esm_default4({message:"Enable verbose mode?",default:config.logging.verbose});return config.logging={tmuxDebug,verbose},config}async function configurePromptMode(config,quick){if(printSection("7. Prompt Mode","Controls how genie injects system prompts into Claude Code"),quick)return console.log(` Using default: promptMode="${config.promptMode}"`),config;console.log(" append \u2014 Uses --append-system-prompt-file (preserves Claude Code default system prompt)"),console.log(" system \u2014 Uses --system-prompt-file (replaces Claude Code default system prompt)"),console.log();let promptMode=await esm_default11({message:"Prompt mode:",choices:[{name:"append (recommended \u2014 preserves CC default)",value:"append"},{name:"system (replaces CC default)",value:"system"}],default:config.promptMode});return config.promptMode=promptMode,config}async function showSummaryAndSave(config){printSection("Summary",`Configuration will be saved to ${contractPath(getGenieConfigPath())}`),console.log(` Session: \x1B[36m${config.session.name}\x1B[0m (window: ${config.session.defaultWindow})`),console.log(` Terminal: timeout=${config.terminal.execTimeout}ms, lines=${config.terminal.readLines}`),console.log(` Shortcuts: ${config.shortcuts.tmuxInstalled?"\x1B[32minstalled\x1B[0m":"\x1B[2mnot installed\x1B[0m"}`),console.log(` Codex: ${config.codex?.configured?"\x1B[32mconfigured\x1B[0m":"\x1B[2mnot configured\x1B[0m"}`),console.log(` Debug: tmux=${config.logging.tmuxDebug}, verbose=${config.logging.verbose}`),console.log(` Prompt mode: \x1B[36m${config.promptMode}\x1B[0m`),console.log(),config.setupComplete=!0,config.lastSetupAt=new Date().toISOString(),await saveGenieConfig(config),console.log("\x1B[32m\u2713 Configuration saved!\x1B[0m")}async function showCurrentConfig(){let config=await loadGenieConfig();console.log(),console.log("\x1B[1mCurrent Genie Configuration\x1B[0m"),console.log(`\x1B[2m${contractPath(getGenieConfigPath())}\x1B[0m`),console.log(),console.log(JSON.stringify(config,null,2)),console.log()}function printNextSteps(){console.log(),console.log("\x1B[1mNext Steps:\x1B[0m"),console.log(),console.log(" Start a session: \x1B[36mgenie\x1B[0m"),console.log(" Watch AI work: \x1B[36mtmux attach -t genie\x1B[0m"),console.log(" Check health: \x1B[36mgenie doctor\x1B[0m"),console.log()}async function setupCommand(options={}){if(options.show){await showCurrentConfig();return}if(options.reset){await resetConfig(),console.log("\x1B[32m\u2713 Configuration reset to defaults.\x1B[0m"),console.log();return}let config=await loadGenieConfig();if(options.shortcuts){printHeader(),await configureShortcuts(config,!1),await markSetupComplete();return}if(options.terminal){printHeader(),config=await configureTerminal(config,!1),await saveGenieConfig(config),console.log("\x1B[32m\u2713 Terminal configuration saved.\x1B[0m");return}if(options.session){printHeader(),config=await configureSession(config,!1),await saveGenieConfig(config),console.log("\x1B[32m\u2713 Session configuration saved.\x1B[0m");return}if(options.codex){if(printHeader(),config=await configureCodex(config,!1),await saveGenieConfig(config),config.codex?.configured)console.log("\x1B[32m\u2713 Codex configuration saved.\x1B[0m");return}let quick=options.quick??!1;if(printHeader(),quick)console.log("\x1B[2mQuick mode: accepting all defaults\x1B[0m");config=await configureSession(config,quick),config=await configureTerminal(config,quick),config=await configureShortcuts(config,quick),config=await configureCodex(config,quick),config=await configureDebug(config,quick),config=await configurePromptMode(config,quick),await showSummaryAndSave(config),installGenieTmuxConf(),printNextSteps()}function installGenieTmuxConf(){let{existsSync:existsSync23,copyFileSync:copyFileSync3,mkdirSync:mkdirSync13,chmodSync:chmodSync2}=__require("fs"),{resolve:resolve4,dirname:dirname9}=__require("path"),genieHome3=process.env.GENIE_HOME??join28(homedir23(),".genie"),dest=join28(genieHome3,"tmux.conf");if(existsSync23(dest))return;let src=[resolve4(__dirname,"..","..","scripts","tmux","genie.tmux.conf"),resolve4(__dirname,"..","scripts","tmux","genie.tmux.conf")].find((p)=>existsSync23(p));if(!src)return;try{mkdirSync13(genieHome3,{recursive:!0}),copyFileSync3(src,dest),console.log(`\x1B[32m\u2713\x1B[0m Installed genie tmux config to ${dest}`)}catch{}let osc52Src=join28(dirname9(src),"osc52-copy.sh"),osc52Dest=join28(genieHome3,"osc52-copy.sh");if(existsSync23(osc52Src))try{copyFileSync3(osc52Src,osc52Dest),chmodSync2(osc52Dest,493)}catch{}}var __dirname="/home/runner/_work/genie/genie/src/genie-commands";var init_setup=__esm(()=>{init_esm14();init_codex_config();init_genie_config2();init_system_detect();init_shortcuts()});var exports_version={};__export(exports_version,{VERSION:()=>VERSION});import{existsSync as existsSync26,readFileSync as readFileSync18}from"fs";import{dirname as dirname9,resolve as resolve4}from"path";function readPackageJson(path3){try{if(!existsSync26(path3))return null;return JSON.parse(readFileSync18(path3,"utf-8"))}catch{return null}}function readVersionFromPackageJson(){let startDir=dirname9(import.meta.dir??__dirname),current=startDir;for(let depth=0;depth<MAX_WALK_DEPTH;depth++){let candidate=resolve4(current,"package.json"),pkg=readPackageJson(candidate);if(pkg?.name===PACKAGE_NAME&&pkg.version)return pkg.version;let parent=dirname9(current);if(parent===current)break;current=parent}current=startDir;for(let depth=0;depth<MAX_WALK_DEPTH;depth++){let candidate=resolve4(current,"package.json"),pkg=readPackageJson(candidate);if(pkg?.version)return pkg.version;let parent=dirname9(current);if(parent===current)break;current=parent}return FALLBACK_VERSION}var __dirname="/home/runner/_work/genie/genie/src/lib",FALLBACK_VERSION="0.0.0-unknown",PACKAGE_NAME="@automagik/genie",MAX_WALK_DEPTH=10,VERSION;var init_version=__esm(()=>{VERSION=readVersionFromPackageJson()});import{execSync as execSync5}from"child_process";function getRecentGitHistory(filePath,cwd){try{let trimmed=execSync5(`git log --oneline -n ${MAX_COMMITS} -- ${JSON.stringify(filePath)}`,{encoding:"utf-8",timeout:5000,cwd,stdio:["pipe","pipe","pipe"]}).trim();if(!trimmed)return null;return trimmed}catch{return null}}async function auditContext(payload){let input=payload.tool_input;if(!input)return;let filePath=input.file_path;if(!filePath)return;let cwd=payload.cwd??process.cwd(),history=getRecentGitHistory(filePath,cwd);if(!history)return;return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:`[audit-context] Recent git history for ${filePath}:
|
|
1038
1038
|
${history}`}}}var MAX_COMMITS=5;var init_audit_context=()=>{};var exports_agent_directory={};__export(exports_agent_directory,{rm:()=>rm3,resolve:()=>resolve5,ls:()=>ls,loadIdentity:()=>loadIdentity,getProjectRoot:()=>getProjectRoot,get:()=>get2,findSessionByRepo:()=>findSessionByRepo,edit:()=>edit,add:()=>add});import{existsSync as existsSync27,lstatSync as lstatSync2}from"fs";import{join as join32}from"path";function validateAgentsMd(dir,allowSymlink){let agentsPath=join32(dir,"AGENTS.md");if(!existsSync27(agentsPath))throw Error(`AGENTS.md not found in ${dir}. Each agent directory must contain an AGENTS.md file.`);if(allowSymlink)return;let stat4=lstatSync2(agentsPath);if(!stat4)throw Error(`AGENTS.md in ${dir} disappeared between exists check and stat.`);if(stat4.isSymbolicLink())throw Error(`AGENTS.md in ${dir} is a symlink. Refusing to register: a symlinked AGENTS.md usually means --dir was pointed at a containing folder rather than the agent's real home (the cwd will be wrong and the agent's brain/runbooks won't be visible). Pass --allow-symlink to override if this is intentional.`);if(!stat4.isFile())throw Error(`AGENTS.md in ${dir} is not a regular file (got ${describeFileType(stat4)}).`)}function describeFileType(stat4){if(stat4.isDirectory())return"directory";if(stat4.isBlockDevice())return"block device";if(stat4.isCharacterDevice())return"character device";if(stat4.isFIFO())return"FIFO";if(stat4.isSocket())return"socket";return"unknown special file"}function getProjectRoot(){if(process.env.GENIE_PROJECT_ROOT)return process.env.GENIE_PROJECT_ROOT;try{let{execSync:execSync6}=__require("child_process");return execSync6("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}async function add(entry2,options){if(!entry2.name||entry2.name.trim()==="")throw Error("Agent name is required.");if(!entry2.dir||entry2.dir.trim()==="")throw Error("Agent directory (--dir) is required.");if(!existsSync27(entry2.dir))throw Error(`Directory does not exist: ${entry2.dir}`);validateAgentsMd(entry2.dir,options?.allowSymlink??!1);let full={...entry2,promptMode:entry2.promptMode??"append",registeredAt:new Date().toISOString()},existing=await resolve5(entry2.name);if(existing&&!existing.builtin)throw Error(`Agent "${entry2.name}" already exists. Use "genie dir edit" to update or "genie dir rm" first.`);let metadata=buildMetadata(full),team=entry2.team??entry2.bridgeTmuxSession??null,{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2();return await sql`
|
|
1039
1039
|
INSERT INTO agents (id, role, custom_name, team, repo_path, started_at, state, metadata)
|
|
1040
1040
|
VALUES (
|
|
@@ -1091,7 +1091,7 @@ ${history}`}}}var MAX_COMMITS=5;var init_audit_context=()=>{};var exports_agent_
|
|
|
1091
1091
|
UPDATE agents
|
|
1092
1092
|
SET metadata = metadata || ${sql.json(metadataPatch)}
|
|
1093
1093
|
WHERE role = ${name}
|
|
1094
|
-
`}catch{}return updated}function loadIdentity(entry2){if(!entry2.dir)return null;let agentsPath=join32(entry2.dir,"AGENTS.md");if(existsSync27(agentsPath))return agentsPath;return null}function builtinToEntry(agent){return{name:agent.name,dir:"",promptMode:agent.promptMode??"append",model:agent.model,roles:[],registeredAt:"(built-in)"}}function isKnownBuiltinName(name){return[...BUILTIN_ROLES,...BUILTIN_COUNCIL_MEMBERS].some((agent)=>agent.name===name)}function roleToEntry(role,team,metadata,createdAt){if(!(metadata&&Object.keys(metadata).length>0)){let builtin=[...BUILTIN_ROLES,...BUILTIN_COUNCIL_MEMBERS].find((b2)=>b2.name===role);if(builtin)return builtinToEntry(builtin)}let registeredAt=(typeof metadata?.registeredAt==="string"?metadata.registeredAt:void 0)??createdAt??"";return{name:role,dir:metadata?.dir||"",promptMode:metadata?.promptMode||"append",model:metadata?.model,roles:Array.isArray(metadata?.roles)?metadata.roles:[],registeredAt,description:metadata?.description,color:metadata?.color,provider:metadata?.provider,permissions:metadata?.permissions,disallowedTools:metadata?.disallowedTools,omniScopes:metadata?.omniScopes,hooks:metadata?.hooks,sdk:metadata?.sdk,bridgeTmuxSession:metadata?.bridgeTmuxSession,...metadata?.repo?{repo:metadata.repo}:team?{repo:team}:{}}}function buildMetadata(entry2){let meta={},assignTruthy=(key)=>{if(entry2[key])meta[key]=entry2[key]};if(assignTruthy("dir"),assignTruthy("repo"),assignTruthy("model"),entry2.promptMode&&entry2.promptMode!=="append")meta.promptMode=entry2.promptMode;if(assignTruthy("description"),assignTruthy("color"),assignTruthy("provider"),entry2.roles&&entry2.roles.length>0)meta.roles=entry2.roles;return assignTruthy("permissions"),assignTruthy("disallowedTools"),assignTruthy("omniScopes"),assignTruthy("hooks"),assignTruthy("sdk"),meta.bridgeTmuxSession=entry2.bridgeTmuxSession??null,meta}function parseMetadata(raw){if(!raw)return{};if(typeof raw==="object"&&!Array.isArray(raw))return raw;if(typeof raw==="string")try{return JSON.parse(raw)}catch{return{}}return{}}var init_agent_directory=__esm(()=>{init_builtin_agents()});function buildSearchNames(recipient,dirEntry){let names=new Set([recipient]);if(dirEntry){if(names.add(dirEntry.entry.name),dirEntry.entry.roles)for(let role of dirEntry.entry.roles)names.add(role)}return names}function buildSpawnArgs(template){let args=["spawn","--provider",template.provider,"--team",template.team];if(template.role)args.push("--role",template.role);if(template.skill)args.push("--skill",template.skill);if(template.cwd)args.push("--cwd",template.cwd);if(template.extraArgs)args.push(...template.extraArgs);return args}async function isRecipientLeader(recipient,teamName){try{let{getTeam:getTeam2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),config=await getTeam2(teamName);return!!config?.leader&&recipient===config.leader}catch{return!1}}function extractAutoSpawnTarget(payload){let input=payload.tool_input;if(!input||input.type!=="message")return null;let recipient=input.recipient;if(!recipient)return null;let teamName=process.env.GENIE_TEAM??payload.team_name;if(!teamName)return null;if(recipient==="team-lead")return null;return{recipient,teamName}}async function executeAutoSpawn(recipient,teamName){let registryMod=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),executorRegistryMod=await Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),directoryMod=await Promise.resolve().then(() => (init_agent_directory(),exports_agent_directory)),existing=(await registryMod.list()).find((a)=>(a.role===recipient||a.id===recipient)&&a.team===teamName);if(existing&&await executorRegistryMod.resolveWorkerLivenessByTransport(existing))return;let dirEntry=await directoryMod.resolve(recipient),templates=await registryMod.listTemplates(),searchNames=buildSearchNames(recipient,dirEntry),template=templates.find((t)=>{if(t.team!==teamName)return!1;return[...searchNames].some((q)=>t.id===q||t.role===q)});if(!template){if(dirEntry)console.error(`[genie-hook] Agent "${recipient}" is registered in directory but has no spawn template in team "${teamName}".`);return}let{spawnSync:spawnSync3}=__require("child_process");spawnSync3("genie",buildSpawnArgs(template),{timeout:1e4,stdio:"ignore",env:{...process.env,GENIE_TEAM:teamName}}),console.error(`[genie-hook] Auto-spawned "${recipient}" in team "${teamName}"`)}async function autoSpawn(payload){let target=extractAutoSpawnTarget(payload);if(!target)return;let{recipient,teamName}=target;if(await isRecipientLeader(recipient,teamName))return;try{await executeAutoSpawn(recipient,teamName)}catch(err){let msg=err instanceof Error?err.message:String(err);return console.error(`[genie-hook] Auto-spawn failed for "${recipient}": ${msg}`),{hookSpecificOutput:{hookEventName:"PreToolUse",additionalContext:`auto-spawn warning: failed to spawn "${recipient}": ${msg}`}}}}import{existsSync as existsSync28}from"fs";import{basename as
|
|
1094
|
+
`}catch{}return updated}function loadIdentity(entry2){if(!entry2.dir)return null;let agentsPath=join32(entry2.dir,"AGENTS.md");if(existsSync27(agentsPath))return agentsPath;return null}function builtinToEntry(agent){return{name:agent.name,dir:"",promptMode:agent.promptMode??"append",model:agent.model,roles:[],registeredAt:"(built-in)"}}function isKnownBuiltinName(name){return[...BUILTIN_ROLES,...BUILTIN_COUNCIL_MEMBERS].some((agent)=>agent.name===name)}function roleToEntry(role,team,metadata,createdAt){if(!(metadata&&Object.keys(metadata).length>0)){let builtin=[...BUILTIN_ROLES,...BUILTIN_COUNCIL_MEMBERS].find((b2)=>b2.name===role);if(builtin)return builtinToEntry(builtin)}let registeredAt=(typeof metadata?.registeredAt==="string"?metadata.registeredAt:void 0)??createdAt??"";return{name:role,dir:metadata?.dir||"",promptMode:metadata?.promptMode||"append",model:metadata?.model,roles:Array.isArray(metadata?.roles)?metadata.roles:[],registeredAt,description:metadata?.description,color:metadata?.color,provider:metadata?.provider,permissions:metadata?.permissions,disallowedTools:metadata?.disallowedTools,omniScopes:metadata?.omniScopes,hooks:metadata?.hooks,sdk:metadata?.sdk,bridgeTmuxSession:metadata?.bridgeTmuxSession,...metadata?.repo?{repo:metadata.repo}:team?{repo:team}:{}}}function buildMetadata(entry2){let meta={},assignTruthy=(key)=>{if(entry2[key])meta[key]=entry2[key]};if(assignTruthy("dir"),assignTruthy("repo"),assignTruthy("model"),entry2.promptMode&&entry2.promptMode!=="append")meta.promptMode=entry2.promptMode;if(assignTruthy("description"),assignTruthy("color"),assignTruthy("provider"),entry2.roles&&entry2.roles.length>0)meta.roles=entry2.roles;return assignTruthy("permissions"),assignTruthy("disallowedTools"),assignTruthy("omniScopes"),assignTruthy("hooks"),assignTruthy("sdk"),meta.bridgeTmuxSession=entry2.bridgeTmuxSession??null,meta}function parseMetadata(raw){if(!raw)return{};if(typeof raw==="object"&&!Array.isArray(raw))return raw;if(typeof raw==="string")try{return JSON.parse(raw)}catch{return{}}return{}}var init_agent_directory=__esm(()=>{init_builtin_agents()});function buildSearchNames(recipient,dirEntry){let names=new Set([recipient]);if(dirEntry){if(names.add(dirEntry.entry.name),dirEntry.entry.roles)for(let role of dirEntry.entry.roles)names.add(role)}return names}function buildSpawnArgs(template){let args=["spawn","--provider",template.provider,"--team",template.team];if(template.role)args.push("--role",template.role);if(template.skill)args.push("--skill",template.skill);if(template.cwd)args.push("--cwd",template.cwd);if(template.extraArgs)args.push(...template.extraArgs);return args}async function isRecipientLeader(recipient,teamName){try{let{getTeam:getTeam2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),config=await getTeam2(teamName);return!!config?.leader&&recipient===config.leader}catch{return!1}}function extractAutoSpawnTarget(payload){let input=payload.tool_input;if(!input||input.type!=="message")return null;let recipient=input.recipient;if(!recipient)return null;let teamName=process.env.GENIE_TEAM??payload.team_name;if(!teamName)return null;if(recipient==="team-lead")return null;return{recipient,teamName}}async function executeAutoSpawn(recipient,teamName){let registryMod=await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),executorRegistryMod=await Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),directoryMod=await Promise.resolve().then(() => (init_agent_directory(),exports_agent_directory)),existing=(await registryMod.list()).find((a)=>(a.role===recipient||a.id===recipient)&&a.team===teamName);if(existing&&await executorRegistryMod.resolveWorkerLivenessByTransport(existing))return;let dirEntry=await directoryMod.resolve(recipient),templates=await registryMod.listTemplates(),searchNames=buildSearchNames(recipient,dirEntry),template=templates.find((t)=>{if(t.team!==teamName)return!1;return[...searchNames].some((q)=>t.id===q||t.role===q)});if(!template){if(dirEntry)console.error(`[genie-hook] Agent "${recipient}" is registered in directory but has no spawn template in team "${teamName}".`);return}let{spawnSync:spawnSync3}=__require("child_process");spawnSync3("genie",buildSpawnArgs(template),{timeout:1e4,stdio:"ignore",env:{...process.env,GENIE_TEAM:teamName}}),console.error(`[genie-hook] Auto-spawned "${recipient}" in team "${teamName}"`)}async function autoSpawn(payload){let target=extractAutoSpawnTarget(payload);if(!target)return;let{recipient,teamName}=target;if(await isRecipientLeader(recipient,teamName))return;try{await executeAutoSpawn(recipient,teamName)}catch(err){let msg=err instanceof Error?err.message:String(err);return console.error(`[genie-hook] Auto-spawn failed for "${recipient}": ${msg}`),{hookSpecificOutput:{hookEventName:"PreToolUse",additionalContext:`auto-spawn warning: failed to spawn "${recipient}": ${msg}`}}}}import{existsSync as existsSync28}from"fs";import{basename as basename4,join as join33}from"path";function sessionKey(payload){return payload.session_id??`${process.pid}`}function isBrainAvailable(){return existsSync28(join33(BRAIN_DIR,"package.json"))}async function queryBrain(cwd){try{let brain=await import(BRAIN_PKG);if(!brain.search)return null;let projectName=basename4(cwd),results=await brain.search({query:`context for ${projectName}`,limit:5,minScore:0.5});if(!results||results.length===0)return null;return results.map((r)=>{return`- ${(r.content??r.text??"").slice(0,200)}`}).join(`
|
|
1095
1095
|
`)}catch{return null}}async function brainInject(payload){let key=sessionKey(payload);if(enrichedSessions.has(key))return;if(enrichedSessions.add(key),!isBrainAvailable())return;let cwd=payload.cwd??process.cwd();try{let context=await queryBrain(cwd);if(!context)return;return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:`[brain-inject] Prior context from knowledge base:
|
|
1096
1096
|
${context}`}}}catch{return}}var BRAIN_PKG="@khal-os/brain",BRAIN_DIR="node_modules/@khal-os/brain",enrichedSessions;var init_brain_inject=__esm(()=>{enrichedSessions=new Set});import{spawnSync as spawnSync3}from"child_process";function extractPrNumber(cmd){let match=cmd.match(/gh\s+pr\s+merge\s+(\d+)\b/);return match?match[1]:null}function extractRepoFlag(cmd){let match=cmd.match(/(?:--repo|-R)(?:\s+|=)([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\b/);return match?match[1]:null}function stepUnquoted(ch){if(ch==="'")return{out:" ",next:"single",consumed:1};if(ch==='"')return{out:" ",next:"double",consumed:1};return{out:ch,next:"none",consumed:1}}function stepSingleQuoted(ch){return{out:" ",next:ch==="'"?"none":"single",consumed:1}}function stepDoubleQuoted(ch,hasNext){if(ch==="\\"&&hasNext)return{out:" ",next:"double",consumed:2};return{out:" ",next:ch==='"'?"none":"double",consumed:1}}function maskQuotedRegions(cmd){let out="",state="none",i2=0;while(i2<cmd.length){let step=state==="double"?stepDoubleQuoted(cmd[i2],i2+1<cmd.length):state==="single"?stepSingleQuoted(cmd[i2]):stepUnquoted(cmd[i2]);out+=step.out,state=step.next,i2+=step.consumed}return out}async function branchGuard(payload,deps=defaultDeps){let input=payload.tool_input;if(!input)return;let command=input.command;if(!command)return;let matchTarget=maskQuotedRegions(command);if(!/\b(git|gh)\b/.test(matchTarget))return;for(let pattern of SYNC_DENY_PATTERNS)if(pattern.test(matchTarget))return{decision:"deny",reason:pattern.reason};if(/gh\s+pr\s+merge\b/.test(matchTarget)){let prNum=extractPrNumber(matchTarget);if(!prNum)return{decision:"deny",reason:"BLOCKED: `gh pr merge` requires an explicit PR number so the target base branch can be verified. \xA719 (v2): agents merge PRs targeting `dev` only; main/master is humans-only via GitHub UI."};let repo=extractRepoFlag(matchTarget)??void 0,resolved=await deps.resolvePrBase(prNum,repo);if("reason"in resolved)return{decision:"deny",reason:`BLOCKED: could not resolve base branch of PR #${prNum} \u2014 ${resolved.reason}. \xA719 (v2): cannot merge without verifying base is \`dev\`. Check the PR exists and try again, or ask a human to merge via GitHub UI.`};let base=resolved.base;if(!ALLOWED_MERGE_BASES.has(base))return{decision:"deny",reason:`BLOCKED: PR #${prNum} targets \`${base}\`. \xA719 (v2): agents may merge PRs targeting \`dev\` only. Main/master merges are humans-only via GitHub UI.`}}return}var ALLOWED_MERGE_BASES,SYNC_DENY_PATTERNS,STDERR_SURFACE_CAP=500,defaultDeps;var init_branch_guard=__esm(()=>{ALLOWED_MERGE_BASES=new Set(["dev"]),SYNC_DENY_PATTERNS=[{test:(cmd)=>/git\s+push\b/i.test(cmd)&&/(?:^|\s)(main|master)(?:\s|$)/.test(cmd),reason:"BLOCKED: Push to main/master is FORBIDDEN. Push to a feature branch and create a PR targeting dev."},{test:(cmd)=>/git\s+push\b/.test(cmd)&&/:(main|master)\b/.test(cmd),reason:"BLOCKED: Push refspec targeting main/master is FORBIDDEN."},{test:(cmd)=>/gh\s+pr\s+create\b/.test(cmd)&&!/(--base|-B)\s+\S/.test(cmd),reason:"BLOCKED: gh pr create requires explicit --base flag. Use: gh pr create --base dev (or --base main for releases)"},{test:(cmd)=>/git\s+checkout\s+(main|master)\s*[;&|]+\s*git\s+(commit|merge|cherry-pick|rebase|push|add)\b/.test(cmd),reason:"BLOCKED: Committing or mutating on main/master is FORBIDDEN. Work on feature branches."}],defaultDeps={async resolvePrBase(prNum,repo){let args=["pr","view",prNum,"--json","baseRefName","-q",".baseRefName"];if(repo)args.push("--repo",repo);let result2;try{result2=spawnSync3("gh",args,{encoding:"utf8",timeout:1e4,stdio:["ignore","pipe","pipe"]})}catch(err){return{reason:`spawnSync threw: ${(err instanceof Error?err.message:String(err)).slice(0,STDERR_SURFACE_CAP)}`}}if(result2.error)return{reason:`subprocess error: ${result2.error.message.slice(0,STDERR_SURFACE_CAP)}`};let stderr=typeof result2.stderr==="string"?result2.stderr.trim():"";if(result2.status!==0){let tail=stderr.slice(-STDERR_SURFACE_CAP)||"no stderr captured";return{reason:`gh pr view exited ${result2.status}: ${tail}`}}let stdout=typeof result2.stdout==="string"?result2.stdout.trim():"";if(!stdout)return{reason:`gh pr view exited 0 with empty stdout (stderr: ${stderr.slice(-STDERR_SURFACE_CAP)||"none"})`};return{base:stdout}}}});function formatEnvelope(input){let source=input.source&&input.source.length>0?input.source:"agent";if(source==="agent")return input.body;let attrs=[`source="${escapeAttr(source)}"`];if(input.from)attrs.push(`from="${escapeAttr(input.from)}"`);if(input.meta)for(let[key,value]of Object.entries(input.meta)){if(!isValidAttrName(key))continue;if(value===void 0||value===null)continue;attrs.push(`${key}="${escapeAttr(stringifyAttr(value))}"`)}return`<channel ${attrs.join(" ")}>${input.body}</channel>`}function escapeAttr(value){return value.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function isValidAttrName(name){return/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(name)}function stringifyAttr(value){if(typeof value==="string")return value;if(typeof value==="number"||typeof value==="boolean")return String(value);return JSON.stringify(value)}var init_channel_envelope=()=>{};function rng(){return crypto.getRandomValues(rnds8)}var rnds8;var init_rng=__esm(()=>{rnds8=new Uint8Array(16)});function unsafeStringify(arr,offset=0){return(byteToHex[arr[offset+0]]+byteToHex[arr[offset+1]]+byteToHex[arr[offset+2]]+byteToHex[arr[offset+3]]+"-"+byteToHex[arr[offset+4]]+byteToHex[arr[offset+5]]+"-"+byteToHex[arr[offset+6]]+byteToHex[arr[offset+7]]+"-"+byteToHex[arr[offset+8]]+byteToHex[arr[offset+9]]+"-"+byteToHex[arr[offset+10]]+byteToHex[arr[offset+11]]+byteToHex[arr[offset+12]]+byteToHex[arr[offset+13]]+byteToHex[arr[offset+14]]+byteToHex[arr[offset+15]]).toLowerCase()}var byteToHex;var init_stringify=__esm(()=>{byteToHex=[];for(let i2=0;i2<256;++i2)byteToHex.push((i2+256).toString(16).slice(1))});function v4(options,buf,offset){if(!buf&&!options&&crypto.randomUUID)return crypto.randomUUID();return _v4(options,buf,offset)}function _v4(options,buf,offset){options=options||{};let rnds=options.random??options.rng?.()??rng();if(rnds.length<16)throw Error("Random bytes length must be >= 16");if(rnds[6]=rnds[6]&15|64,rnds[8]=rnds[8]&63|128,buf){if(offset=offset||0,offset<0||offset+16>buf.length)throw RangeError(`UUID byte range ${offset}:${offset+15} is out of buffer bounds`);for(let i2=0;i2<16;++i2)buf[offset+i2]=rnds[i2];return buf}return unsafeStringify(rnds)}var v4_default;var init_v4=__esm(()=>{init_rng();init_stringify();v4_default=v4});var init_dist_node=__esm(()=>{init_v4()});var exports_runtime_events={};__export(exports_runtime_events,{waitForRuntimeEvent:()=>waitForRuntimeEvent,queryRuntimeEventThroughput:()=>queryRuntimeEventThroughput,publishSubjectEvent:()=>publishSubjectEvent,publishRuntimeEvent:()=>publishRuntimeEvent,listRuntimeEvents:()=>listRuntimeEvents,getLatestRuntimeEventId:()=>getLatestRuntimeEventId,followRuntimeEvents:()=>followRuntimeEvents});class EventCircuitBreaker{failures=0;lastFailure=0;loggedOpen=!1;threshold=5;cooldown=30000;isOpen(){if(this.failures<this.threshold)return!1;if(Date.now()-this.lastFailure>this.cooldown)return this.failures=0,!1;return!0}recordSuccess(){if(this.failures>=this.threshold)console.warn("[runtime-events] circuit breaker closed \u2014 PG writes resumed");this.failures=0,this.loggedOpen=!1}recordFailure(){if(this.failures++,this.lastFailure=Date.now(),this.failures>=this.threshold&&!this.loggedOpen)console.warn(`[runtime-events] circuit breaker open \u2014 skipping PG writes for ${this.cooldown/1000}s after ${this.threshold} consecutive failures`),this.loggedOpen=!0}get state(){if(this.failures<this.threshold)return"closed";if(Date.now()-this.lastFailure>this.cooldown)return"half-open";return"open"}}function logFollowDrainError(context,error2,active){if(!active)return;let message=error2 instanceof Error?error2.message:String(error2);console.error(`[runtime-events] ${context} drain failed: ${message}`)}function rowToRuntimeEvent(row){return{id:Number(row.id),repoPath:row.repo_path,timestamp:row.created_at instanceof Date?row.created_at.toISOString():String(row.created_at),kind:row.kind,agent:row.agent,team:row.team??void 0,direction:row.direction??void 0,peer:row.peer??void 0,text:row.text,data:row.data??void 0,source:row.source,subject:row.subject??void 0,threadId:row.thread_id??void 0,traceId:row.trace_id??void 0,parentEventId:row.parent_event_id!=null?Number(row.parent_event_id):void 0}}function nextParam(values2,value){return values2.push(value),`$${values2.length}`}function buildScopeClause(query,values2){let scopeClauses=[];if(query.agentIds&&query.agentIds.length>0)scopeClauses.push(`agent = ANY(${nextParam(values2,query.agentIds)})`);if(query.team)scopeClauses.push(`team = ${nextParam(values2,query.team)}`);if(query.teamPrefix)scopeClauses.push(`team LIKE ${nextParam(values2,`${query.teamPrefix}%`)}`);if(scopeClauses.length===0)return null;if(scopeClauses.length===1)return scopeClauses[0];if(query.scopeMode==="any")return`(${scopeClauses.join(" OR ")})`;return`(${scopeClauses.join(" AND ")})`}function buildWhere(query){let values2=[],clauses=[];if(query.afterId!=null)clauses.push(`id > ${nextParam(values2,query.afterId)}`);if(query.repoPath)clauses.push(`repo_path = ${nextParam(values2,query.repoPath)}`);if(query.subject)clauses.push(`subject = ${nextParam(values2,query.subject)}`);if(query.kinds&&query.kinds.length>0)clauses.push(`kind = ANY(${nextParam(values2,query.kinds)})`);if(query.since)clauses.push(`created_at >= ${nextParam(values2,query.since)}`);if(query.threadId)clauses.push(`thread_id = ${nextParam(values2,query.threadId)}`);if(query.traceId)clauses.push(`trace_id = ${nextParam(values2,query.traceId)}`);let scopeClause=buildScopeClause(query,values2);if(scopeClause)clauses.push(scopeClause);return{clause:clauses.length>0?`WHERE ${clauses.join(" AND ")}`:"",values:values2}}async function publishRuntimeEvent(input){if(circuitBreaker.isOpen())throw Error("circuit breaker open \u2014 PG event write skipped");try{let sql=await getConnection(),threadId=input.threadId??`agent:${input.agent}`,rows=await sql`
|
|
1097
1097
|
INSERT INTO genie_runtime_events (
|
|
@@ -1176,10 +1176,10 @@ ${context}`}}}catch{return}}var BRAIN_PKG="@khal-os/brain",BRAIN_DIR="node_modul
|
|
|
1176
1176
|
`+` genie task status <slug> \u2014 check progress
|
|
1177
1177
|
`+" 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:
|
|
1178
1178
|
genie task status <slug>
|
|
1179
|
-
genie events list --since 5m`}]});import{existsSync as existsSync29,readFileSync as readFileSync19}from"fs";import{basename as
|
|
1179
|
+
genie events list --since 5m`}]});import{existsSync as existsSync29,readFileSync as readFileSync19}from"fs";import{basename as basename5,join as join34}from"path";function readAgentNameFromSettings(cwd){let localSettings=join34(cwd,".claude","settings.local.json");if(!existsSync29(localSettings))return;try{return JSON.parse(readFileSync19(localSettings,"utf-8")).agentName||void 0}catch{return}}function nameFromCwd(cwd){let name=basename5(cwd);return name&&name!=="/"&&name!=="."?name:void 0}function resolveAgentName(payload){let cwd=payload.cwd;return process.env.GENIE_AGENT_NAME||payload.teammate_name||cwd&&readAgentNameFromSettings(cwd)||cwd&&nameFromCwd(cwd)||payload.session_id&&`session-${payload.session_id.slice(0,8)}`||"unknown"}function resolveTeamName(payload){return payload.team_name??process.env.GENIE_TEAM??void 0}var init_resolve_agent_name=()=>{};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(`
|
|
1180
1180
|
`)[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 existsSync30,mkdirSync as mkdirSync14,readFileSync as readFileSync20,renameSync as renameSync5,writeFileSync as writeFileSync12}from"fs";import{homedir as homedir27}from"os";import{join as join35}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(_deps2).some((v)=>v!==null),testCacheOverridden=typeof globalThis.__GENIE_SESSION_SYNC_CACHE_FILE==="string";if((hasOverrides||!1||!1)&&!testCacheOverridden)return;try{let cacheFile=effectiveCacheFile();if(!existsSync30(cacheFile))return;let parsed=JSON.parse(readFileSync20(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(_deps2).some((v)=>v!==null),testCacheOverridden=typeof globalThis.__GENIE_SESSION_SYNC_CACHE_FILE==="string";if((hasOverrides||!1||!1)&&!testCacheOverridden)return;try{let cacheFile=effectiveCacheFile();mkdirSync14(join35(cacheFile,".."),{recursive:!0}),trimCache();let obj=Object.fromEntries(syncedSessions),tmp=`${cacheFile}.tmp.${process.pid}`;writeFileSync12(tmp,JSON.stringify(obj)),renameSync5(tmp,cacheFile)}catch{}}async function resolveDeps2(){let[agentMod,execMod,audit]=await Promise.all([_deps2.getAgentByName?null:Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry)),_deps2.getExecutor&&_deps2.updateClaudeSessionId?null:Promise.resolve().then(() => (init_executor_registry(),exports_executor_registry)),_deps2.emitAuditEvent?null:Promise.resolve().then(() => (init_audit(),exports_audit))]);return{getAgentByName:_deps2.getAgentByName??agentMod.getAgentByName,getExecutor:_deps2.getExecutor??execMod.getExecutor,updateClaudeSessionId:_deps2.updateClaudeSessionId??execMod.updateClaudeSessionId,emitAuditEvent:_deps2.emitAuditEvent??audit.recordAuditEvent}}function shouldSkipSync(payload){let sessionId=payload.session_id;if(!sessionId||typeof sessionId!=="string")return null;let hasOverrides=Object.values(_deps2).some((v)=>v!==null),agentName=process.env.GENIE_AGENT_NAME??payload.teammate_name,teamName=process.env.GENIE_TEAM??payload.team_name;if(!agentName||!teamName)return null;return{sessionId,agentName,teamName}}async function sessionSync(payload){try{let ctx=shouldSkipSync(payload);if(!ctx)return;loadDiskCache();let deps=await resolveDeps2(),executorId=(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,_deps2,TERMINAL_EXECUTOR_STATES;var init_session_sync=__esm(()=>{syncedSessions=new Map,GENIE_HOME3=process.env.GENIE_HOME??join35(homedir27(),".genie"),DEFAULT_CACHE_FILE=join35(GENIE_HOME3,"cache","session-sync.json");_deps2={getAgentByName:null,getExecutor:null,updateClaudeSessionId:null,emitAuditEvent:null};TERMINAL_EXECUTOR_STATES=new Set(["done","error","terminated"])});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=process.env.GENIE_AGENT_NAME??"unknown",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}):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});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});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){let response={},hasContext=contextMessages.length>0,hasInputChange=currentInput&&originalInput&&JSON.stringify(currentInput)!==JSON.stringify(originalInput);if(hasInputChange)response.updatedInput=currentInput;if(hookEventName==="PreToolUse"&&(hasContext||hasInputChange)){let output={hookEventName:"PreToolUse"};if(hasContext)output.additionalContext=contextMessages.join(`
|
|
1181
1181
|
`);if(hasInputChange)output.permissionDecision="allow",output.updatedInput=currentInput;response.hookSpecificOutput=output}if(hookEventName==="UserPromptSubmit"&&hasContext)response.hookSpecificOutput={hookEventName:"UserPromptSubmit",additionalContext:contextMessages.join(`
|
|
1182
|
-
`)};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)}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;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_orchestration_guard();init_runtime_emit();init_session_sync();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])});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:mkdirSync15,writeFileSync:writeFileSync13}=await import("fs"),{basename:
|
|
1182
|
+
`)};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)}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;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_orchestration_guard();init_runtime_emit();init_session_sync();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])});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:mkdirSync15,writeFileSync:writeFileSync13}=await import("fs"),{basename:basename6,join:join36}=await import("path"),cwd=process.cwd(),genieDir=join36(cwd,".genie");mkdirSync15(genieDir,{recursive:!0});let config={name:basename6(cwd),agents:{defaults:{}},tmux:{socket:"genie"},sdk:{}};writeFileSync13(join36(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
|
|
1183
1183
|
`),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 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 attrs=attrsToObject(resource?.attributes);return{agentName:attrs["agent.name"],teamName:attrs["team.name"],wishSlug:attrs["wish.slug"],sessionId:attrs["session.id"],agentRole:attrs["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:getActivePort()+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=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,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=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=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`
|
|
1184
1184
|
INSERT INTO audit_events (entity_type, entity_id, event_type, actor, details)
|
|
1185
1185
|
SELECT * FROM unnest(
|
|
@@ -1546,7 +1546,7 @@ Synced: ${total} agent(s), ${result2.archived.length} removed.`)}async function
|
|
|
1546
1546
|
AND actor_id = ${actor.actorId}
|
|
1547
1547
|
AND channel = ${channel}
|
|
1548
1548
|
`).count>0}async function listTasksForActor(actor,filters={}){let sql=await getConnection(),conditions=[],values2=[],paramIdx=1;if(filters.projectName)conditions.push(`t.project_id = (SELECT id FROM projects WHERE name = $${paramIdx++})`),values2.push(filters.projectName);else if(filters.allProjects);else conditions.push(`t.repo_path = $${paramIdx++}`),values2.push(filters.repoPath??getRepoPath());if(conditions.push(`ta.actor_type = $${paramIdx++}`),values2.push(actor.actorType),conditions.push(`ta.actor_id = $${paramIdx++}`),values2.push(actor.actorId),filters.stage)conditions.push(`t.stage = $${paramIdx++}`),values2.push(filters.stage);if(filters.status)conditions.push(`t.status = $${paramIdx++}`),values2.push(filters.status);else if(!filters.includeArchived)conditions.push("t.status != 'archived'");if(filters.priority)conditions.push(`t.priority = $${paramIdx++}`),values2.push(filters.priority);let limit=filters.limit??100,offset=filters.offset??0;values2.push(limit,offset);let query=`SELECT DISTINCT t.* FROM tasks t JOIN task_actors ta ON ta.task_id = t.id WHERE ${conditions.join(" AND ")} ORDER BY t.created_at DESC LIMIT $${paramIdx++} OFFSET $${paramIdx++}`;return(await sql.unsafe(query,values2)).map(mapTask)}var init_task_service=__esm(()=>{init_genie_tokens();init_audit();init_db()});import{createHash as createHash3}from"crypto";function parseRoutingHeader(text){if(!text)return null;let match=text.split(`
|
|
1549
|
-
`)[0].trim().match(/^\[(.+)\]$/);if(!match)return null;let pairs2=match[1].split(/\s+/),fields={};for(let pair of pairs2){let colonIdx=pair.indexOf(":");if(colonIdx<=0)continue;let key=pair.slice(0,colonIdx),value=pair.slice(colonIdx+1);if(key&&value)fields[key]=value}for(let field of REQUIRED_FIELDS)if(!fields[field])return null;if(fields.type!=="dm"&&fields.type!=="group")return null;return{channel:fields.channel,instance:fields.instance,chat:fields.chat,msg:fields.msg,from:fields.from,type:fields.type,thread:fields.thread,replyTo:fields.replyTo}}function shortHash(input){return createHash3("sha256").update(input).digest("hex").slice(0,8)}function resolveSessionKey(agentName,header){let chatId=shortHash(`${header.channel}-${header.instance}-${header.chat}`),base=`${agentName}-${chatId}`;if(header.thread)return`${base}-${header.thread}`;return base}var REQUIRED_FIELDS;var init_routing_header=__esm(()=>{REQUIRED_FIELDS=["channel","instance","chat","msg","from","type"]});var exports_session={};__export(exports_session,{sessionCommand:()=>sessionCommand,sanitizeWindowName:()=>sanitizeWindowName,getAgentsFilePath:()=>getAgentsFilePath,buildClaudeCommand:()=>buildClaudeCommand2});import{spawnSync as spawnSync4}from"child_process";import{createHash as createHash4,randomUUID as randomUUID5}from"crypto";import{existsSync as existsSync33}from"fs";import{basename as basename5,join as join38}from"path";function shortPathHash(p){return createHash4("md5").update(p).digest("hex").slice(0,4)}function getAgentsFilePath(){let agentsPath=join38(process.cwd(),"AGENTS.md");if(existsSync33(agentsPath))return agentsPath;return null}async function resolveSessionLeaderName(teamName){try{let{resolveLeaderName:resolveLeaderName2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager));return await resolveLeaderName2(teamName)}catch{return teamName}}async function ensureNativeTeamForLeader(teamName,cwd,sessionId){let leaderName=await resolveSessionLeaderName(teamName);await ensureNativeTeamWithSessionId(teamName,`Genie team: ${teamName}`,sessionId,leaderName),await registerNativeMember(teamName,{agentName:basename5(cwd),agentType:leaderName,color:"blue",cwd})}function buildClaudeCommand2(teamName,systemPromptFile,leaderName,sessionId,resume){return buildTeamLeadCommand(teamName,{systemPromptFile,leaderName,sessionId,resume})}async function registerSessionInRegistry(sessionName,windowName,workspaceDir){try{let target=`${sessionName}:${windowName}`,paneId=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_id}'`)).trim(),now=new Date().toISOString(),sanitized=sanitizeTeamName(windowName),leaderName=await resolveSessionLeaderName(windowName),sanitizedLeader=sanitizeTeamName(leaderName);await register({id:`${sanitized}-${sanitizedLeader}`,paneId,session:sessionName,team:windowName,role:leaderName,worktree:null,startedAt:now,state:"working",lastStateChange:now,repoPath:workspaceDir,provider:"claude",transport:"tmux",nativeTeamEnabled:!0,nativeAgentId:`${sanitizedLeader}@${sanitized}`});let agentIdentity=await findOrCreateAgent(leaderName,sanitized,leaderName),pid=null;try{let pidStr=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_pid}'`)).trim(),parsed=Number.parseInt(pidStr,10);if(parsed>0)pid=parsed}catch{}await createAndLinkExecutor(agentIdentity.id,"claude","tmux",{pid,tmuxSession:sessionName,tmuxPaneId:paneId,tmuxWindow:windowName,state:"running",repoPath:workspaceDir})}catch{}}async function resolveWindowName(sessionName,cwd){let baseName=sanitizeWindowName(basename5(cwd));if(!await findWindowByName(sessionName,baseName))return baseName;if(await getWindowEnv(`${sessionName}:${baseName}`,"GENIE_CWD")===cwd)return baseName;return`${baseName}-${shortPathHash(cwd)}`}async function createSession2(sessionName,windowName,workspaceDir,systemPromptFile,leaderName){let sessionId=randomUUID5(),shouldResume=!1;if(await ensureNativeTeamForLeader(windowName,workspaceDir,sessionId),console.log(`Native team "${windowName}" ready at ~/.claude/teams/${sanitizeTeamName(windowName)}/`),console.log(`Creating session "${sessionName}"...`),!await createSession(sessionName))console.error(`Failed to create session "${sessionName}"`),process.exit(1);let firstWindow=(await listWindows(sessionName))[0];if(!firstWindow)console.error(`Failed to find initial window in session "${sessionName}"`),process.exit(1);await executeTmux2(`rename-window -t ${shellQuote(firstWindow.id)} ${shellQuote(windowName)}`),await executeTmux2(`set-window-option -t ${shellQuote(firstWindow.id)} automatic-rename off`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workspaceDir);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workspaceDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`);let agentName=basename5(workspaceDir),cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,leaderName,sessionId,!1);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),console.log(`Started Claude Code as ${agentName} in ${workspaceDir}`);try{let sanitized=sanitizeTeamName(windowName),leaderName2=await resolveSessionLeaderName(windowName),agentIdentity=await findOrCreateAgent(leaderName2,sanitized,leaderName2);await terminateActiveExecutor(agentIdentity.id)}catch{}await registerSessionInRegistry(sessionName,windowName,workspaceDir)}async function launchWithContinueFallback(target,windowName,workspaceDir,systemPromptFile,leaderName,sessionId,shouldResume){let cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,leaderName,sessionId,shouldResume);if(await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),shouldResume){await new Promise((r)=>setTimeout(r,3000));let afterCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(afterCmd)){console.log("Resume failed unexpectedly, starting fresh session...");let freshId=randomUUID5();await ensureNativeTeamForLeader(windowName,workspaceDir,freshId);let freshCmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,leaderName,freshId,!1);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(freshCmd)} Enter`)}}}async function focusTeamWindow(sessionName,windowName,workingDir,systemPromptFile,leaderName){if((await ensureTeamWindow(sessionName,windowName,workingDir)).created){console.log(`Created team window "${windowName}"`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workingDir);let sessionId=randomUUID5(),shouldResume=!1;await ensureNativeTeamForLeader(windowName,workingDir,sessionId);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,workingDir,systemPromptFile,leaderName,sessionId,shouldResume),console.log(`Started Claude Code as ${basename5(workingDir)}@${sanitizeTeamName(windowName)} in ${workingDir}`);try{let sanitized=sanitizeTeamName(windowName),leaderName2=await resolveSessionLeaderName(windowName),agentIdentity=await findOrCreateAgent(leaderName2,sanitized,leaderName2);await terminateActiveExecutor(agentIdentity.id)}catch{}await registerSessionInRegistry(sessionName,windowName,workingDir)}else{let target=`${sessionName}:${windowName}`,currentCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(currentCmd)){console.log(`Claude Code not running in "${windowName}", relaunching...`);let sessionId=randomUUID5(),shouldResume=!1;await ensureNativeTeamForLeader(windowName,workingDir,sessionId);let cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,workingDir,systemPromptFile,leaderName,sessionId,shouldResume);try{let sanitized=sanitizeTeamName(windowName),leaderName2=await resolveSessionLeaderName(windowName),agentIdentity=await findOrCreateAgent(leaderName2,sanitized,leaderName2);await terminateActiveExecutor(agentIdentity.id)}catch{}await registerSessionInRegistry(sessionName,windowName,workingDir)}}await executeTmux2(`select-window -t ${shellQuote(`${sessionName}:${windowName}`)}`),console.log(`Focused team window "${windowName}"`)}function sanitizeWindowName(name){return name.replace(/\./g,"-")}async function deriveWindowName(sessionName,workspaceDir,team){if(team)return sanitizeWindowName(team);if(await findSessionByName(sessionName))return sanitizeWindowName(await resolveWindowName(sessionName,workspaceDir));return sanitizeWindowName(basename5(workspaceDir))}async function handleReset(sessionName,windowName){let existing=await findSessionByName(sessionName);if(existing){let windows=await listWindows(existing.id);console.log(`Resetting session "${sessionName}"...`),await killSession(existing.id),await Promise.all(windows.map((w)=>deleteNativeTeam(w.name)))}else await deleteNativeTeam(windowName)}function attachToWindow(sessionName,windowName){console.log("Attaching...");let target=`${sessionName}:${windowName}`,cmd=process.env.TMUX?"switch-client":"attach",{genieTmuxPrefix:genieTmuxPrefix2}=(init_tmux_wrapper(),__toCommonJS(exports_tmux_wrapper)),{tmuxBin:tmuxBin2}=(init_ensure_tmux(),__toCommonJS(exports_ensure_tmux));spawnSync4(tmuxBin2(),[...genieTmuxPrefix2(),cmd,"-t",target],{stdio:"inherit"})}async function reconcileLeaderConfigs(){try{let{readdirSync:readdirSync10,readFileSync:readFileSync22,writeFileSync:writeFileSync14}=await import("fs"),{join:join39}=await import("path"),{resolveLeaderName:resolveLeaderName2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),teamsDir=join39(process.env.HOME??"/root",".claude","teams"),teams=readdirSync10(teamsDir);for(let team of teams)try{let configPath2=join39(teamsDir,team,"config.json"),raw=readFileSync22(configPath2,"utf-8"),config=JSON.parse(raw);if(config.leadAgentId?.startsWith("team-lead@")){let actualLeader=await resolveLeaderName2(team),sanitized=sanitizeTeamName(team);config.leadAgentId=`${sanitizeTeamName(actualLeader)}@${sanitized}`,writeFileSync14(configPath2,JSON.stringify(config,null,2)),console.log(`[reconcile] Updated leadAgentId for team "${team}": ${config.leadAgentId}`)}}catch{}}catch{}}async function launchInsideTmux(windowName,workspaceDir,systemPromptFile,leaderName){let sessionId=randomUUID5(),suffix=Date.now().toString(36).slice(-4),currentWindowName=`${windowName}-${suffix}`;await executeTmux2(`rename-window ${shellQuote(currentWindowName)}`),await ensureNativeTeamForLeader(currentWindowName,workspaceDir,sessionId);let cmd=buildClaudeCommand2(currentWindowName,systemPromptFile||void 0,leaderName,sessionId,!1),{execSync:execSyncCmd}=__require("child_process");execSyncCmd(cmd,{stdio:"inherit",cwd:workspaceDir})}async function sessionCommand(options={}){await reconcileStaleSpawns(),await reconcileLeaderConfigs();let workspaceDir=options.dir??process.cwd(),sessionName=options.name??sanitizeWindowName(basename5(workspaceDir));try{let windowName=await deriveWindowName(sessionName,workspaceDir,options.team),leaderName=await resolveSessionLeaderName(windowName);if(options.reset)await handleReset(sessionName,windowName);let session=await findSessionByName(sessionName),systemPromptFile=getAgentsFilePath();if(!systemPromptFile)if(await esm_default4({message:"No agent found in this directory. Scaffold one?",default:!0}))scaffoldAgentFiles(workspaceDir),systemPromptFile=join38(workspaceDir,"AGENTS.md"),console.log("Created SOUL.md, HEARTBEAT.md, and AGENTS.md");else console.error("AGENTS.md required. Run `genie` again to scaffold."),process.exit(1);if(!session)await createSession2(sessionName,windowName,workspaceDir,systemPromptFile,leaderName),attachToWindow(sessionName,windowName);else if(process.env.TMUX)await launchInsideTmux(windowName,workspaceDir,systemPromptFile,leaderName);else console.log(`Session "${sessionName}" already exists`),await focusTeamWindow(sessionName,windowName,workspaceDir,systemPromptFile,leaderName),attachToWindow(sessionName,windowName)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}var init_session=__esm(()=>{init_esm14();init_agent_registry();init_agent_registry();init_claude_native_teams();init_executor_registry();init_team_lead_command();init_tmux();init_templates()});var exports_should_resume={};__export(exports_should_resume,{shouldResume:()=>shouldResume,emitBootPassEvent:()=>emitBootPassEvent,classifyBootPass:()=>classifyBootPass,bootPassEventType:()=>bootPassEventType,bootPassDecisions:()=>bootPassDecisions,BOOT_PASS_CONCURRENCY_CAP:()=>BOOT_PASS_CONCURRENCY_CAP});async function readAgentResumeRow(agentId){return(await(await getConnection())`
|
|
1549
|
+
`)[0].trim().match(/^\[(.+)\]$/);if(!match)return null;let pairs2=match[1].split(/\s+/),fields={};for(let pair of pairs2){let colonIdx=pair.indexOf(":");if(colonIdx<=0)continue;let key=pair.slice(0,colonIdx),value=pair.slice(colonIdx+1);if(key&&value)fields[key]=value}for(let field of REQUIRED_FIELDS)if(!fields[field])return null;if(fields.type!=="dm"&&fields.type!=="group")return null;return{channel:fields.channel,instance:fields.instance,chat:fields.chat,msg:fields.msg,from:fields.from,type:fields.type,thread:fields.thread,replyTo:fields.replyTo}}function shortHash(input){return createHash3("sha256").update(input).digest("hex").slice(0,8)}function resolveSessionKey(agentName,header){let chatId=shortHash(`${header.channel}-${header.instance}-${header.chat}`),base=`${agentName}-${chatId}`;if(header.thread)return`${base}-${header.thread}`;return base}var REQUIRED_FIELDS;var init_routing_header=__esm(()=>{REQUIRED_FIELDS=["channel","instance","chat","msg","from","type"]});var exports_session={};__export(exports_session,{sessionCommand:()=>sessionCommand,sanitizeWindowName:()=>sanitizeWindowName,getAgentsFilePath:()=>getAgentsFilePath,buildClaudeCommand:()=>buildClaudeCommand2});import{spawnSync as spawnSync4}from"child_process";import{createHash as createHash4,randomUUID as randomUUID5}from"crypto";import{existsSync as existsSync33}from"fs";import{basename as basename6,join as join38}from"path";function shortPathHash(p){return createHash4("md5").update(p).digest("hex").slice(0,4)}function getAgentsFilePath(){let agentsPath=join38(process.cwd(),"AGENTS.md");if(existsSync33(agentsPath))return agentsPath;return null}async function resolveSessionLeaderName(teamName){try{let{resolveLeaderName:resolveLeaderName2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager));return await resolveLeaderName2(teamName)}catch{return teamName}}async function ensureNativeTeamForLeader(teamName,cwd,sessionId){let leaderName=await resolveSessionLeaderName(teamName);await ensureNativeTeamWithSessionId(teamName,`Genie team: ${teamName}`,sessionId,leaderName),await registerNativeMember(teamName,{agentName:basename6(cwd),agentType:leaderName,color:"blue",cwd})}function buildClaudeCommand2(teamName,systemPromptFile,leaderName,sessionId,resume){return buildTeamLeadCommand(teamName,{systemPromptFile,leaderName,sessionId,resume})}async function registerSessionInRegistry(sessionName,windowName,workspaceDir){try{let target=`${sessionName}:${windowName}`,paneId=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_id}'`)).trim(),now=new Date().toISOString(),sanitized=sanitizeTeamName(windowName),leaderName=await resolveSessionLeaderName(windowName),sanitizedLeader=sanitizeTeamName(leaderName);await register({id:`${sanitized}-${sanitizedLeader}`,paneId,session:sessionName,team:windowName,role:leaderName,worktree:null,startedAt:now,state:"working",lastStateChange:now,repoPath:workspaceDir,provider:"claude",transport:"tmux",nativeTeamEnabled:!0,nativeAgentId:`${sanitizedLeader}@${sanitized}`});let agentIdentity=await findOrCreateAgent(leaderName,sanitized,leaderName),pid=null;try{let pidStr=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_pid}'`)).trim(),parsed=Number.parseInt(pidStr,10);if(parsed>0)pid=parsed}catch{}await createAndLinkExecutor(agentIdentity.id,"claude","tmux",{pid,tmuxSession:sessionName,tmuxPaneId:paneId,tmuxWindow:windowName,state:"running",repoPath:workspaceDir})}catch{}}async function resolveWindowName(sessionName,cwd){let baseName=sanitizeWindowName(basename6(cwd));if(!await findWindowByName(sessionName,baseName))return baseName;if(await getWindowEnv(`${sessionName}:${baseName}`,"GENIE_CWD")===cwd)return baseName;return`${baseName}-${shortPathHash(cwd)}`}async function createSession2(sessionName,windowName,workspaceDir,systemPromptFile,leaderName){let sessionId=randomUUID5(),shouldResume=!1;if(await ensureNativeTeamForLeader(windowName,workspaceDir,sessionId),console.log(`Native team "${windowName}" ready at ~/.claude/teams/${sanitizeTeamName(windowName)}/`),console.log(`Creating session "${sessionName}"...`),!await createSession(sessionName))console.error(`Failed to create session "${sessionName}"`),process.exit(1);let firstWindow=(await listWindows(sessionName))[0];if(!firstWindow)console.error(`Failed to find initial window in session "${sessionName}"`),process.exit(1);await executeTmux2(`rename-window -t ${shellQuote(firstWindow.id)} ${shellQuote(windowName)}`),await executeTmux2(`set-window-option -t ${shellQuote(firstWindow.id)} automatic-rename off`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workspaceDir);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workspaceDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`);let agentName=basename6(workspaceDir),cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,leaderName,sessionId,!1);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),console.log(`Started Claude Code as ${agentName} in ${workspaceDir}`);try{let sanitized=sanitizeTeamName(windowName),leaderName2=await resolveSessionLeaderName(windowName),agentIdentity=await findOrCreateAgent(leaderName2,sanitized,leaderName2);await terminateActiveExecutor(agentIdentity.id)}catch{}await registerSessionInRegistry(sessionName,windowName,workspaceDir)}async function launchWithContinueFallback(target,windowName,workspaceDir,systemPromptFile,leaderName,sessionId,shouldResume){let cmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,leaderName,sessionId,shouldResume);if(await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cmd)} Enter`),shouldResume){await new Promise((r)=>setTimeout(r,3000));let afterCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(afterCmd)){console.log("Resume failed unexpectedly, starting fresh session...");let freshId=randomUUID5();await ensureNativeTeamForLeader(windowName,workspaceDir,freshId);let freshCmd=buildClaudeCommand2(windowName,systemPromptFile||void 0,leaderName,freshId,!1);await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(freshCmd)} Enter`)}}}async function focusTeamWindow(sessionName,windowName,workingDir,systemPromptFile,leaderName){if((await ensureTeamWindow(sessionName,windowName,workingDir)).created){console.log(`Created team window "${windowName}"`),await setWindowEnv(`${sessionName}:${windowName}`,"GENIE_CWD",workingDir);let sessionId=randomUUID5(),shouldResume=!1;await ensureNativeTeamForLeader(windowName,workingDir,sessionId);let target=`${sessionName}:${windowName}`,cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,workingDir,systemPromptFile,leaderName,sessionId,shouldResume),console.log(`Started Claude Code as ${basename6(workingDir)}@${sanitizeTeamName(windowName)} in ${workingDir}`);try{let sanitized=sanitizeTeamName(windowName),leaderName2=await resolveSessionLeaderName(windowName),agentIdentity=await findOrCreateAgent(leaderName2,sanitized,leaderName2);await terminateActiveExecutor(agentIdentity.id)}catch{}await registerSessionInRegistry(sessionName,windowName,workingDir)}else{let target=`${sessionName}:${windowName}`,currentCmd=(await executeTmux2(`display -t ${shellQuote(target)} -p '#{pane_current_command}'`)).trim();if(["bash","zsh","sh","fish"].includes(currentCmd)){console.log(`Claude Code not running in "${windowName}", relaunching...`);let sessionId=randomUUID5(),shouldResume=!1;await ensureNativeTeamForLeader(windowName,workingDir,sessionId);let cdCmd=`cd ${shellQuote(workingDir)}`;await executeTmux2(`send-keys -t ${shellQuote(target)} ${shellQuote(cdCmd)} Enter`),await launchWithContinueFallback(target,windowName,workingDir,systemPromptFile,leaderName,sessionId,shouldResume);try{let sanitized=sanitizeTeamName(windowName),leaderName2=await resolveSessionLeaderName(windowName),agentIdentity=await findOrCreateAgent(leaderName2,sanitized,leaderName2);await terminateActiveExecutor(agentIdentity.id)}catch{}await registerSessionInRegistry(sessionName,windowName,workingDir)}}await executeTmux2(`select-window -t ${shellQuote(`${sessionName}:${windowName}`)}`),console.log(`Focused team window "${windowName}"`)}function sanitizeWindowName(name){return name.replace(/\./g,"-")}async function deriveWindowName(sessionName,workspaceDir,team){if(team)return sanitizeWindowName(team);if(await findSessionByName(sessionName))return sanitizeWindowName(await resolveWindowName(sessionName,workspaceDir));return sanitizeWindowName(basename6(workspaceDir))}async function handleReset(sessionName,windowName){let existing=await findSessionByName(sessionName);if(existing){let windows=await listWindows(existing.id);console.log(`Resetting session "${sessionName}"...`),await killSession(existing.id),await Promise.all(windows.map((w)=>deleteNativeTeam(w.name)))}else await deleteNativeTeam(windowName)}function attachToWindow(sessionName,windowName){console.log("Attaching...");let target=`${sessionName}:${windowName}`,cmd=process.env.TMUX?"switch-client":"attach",{genieTmuxPrefix:genieTmuxPrefix2}=(init_tmux_wrapper(),__toCommonJS(exports_tmux_wrapper)),{tmuxBin:tmuxBin2}=(init_ensure_tmux(),__toCommonJS(exports_ensure_tmux));spawnSync4(tmuxBin2(),[...genieTmuxPrefix2(),cmd,"-t",target],{stdio:"inherit"})}async function reconcileLeaderConfigs(){try{let{readdirSync:readdirSync10,readFileSync:readFileSync22,writeFileSync:writeFileSync14}=await import("fs"),{join:join39}=await import("path"),{resolveLeaderName:resolveLeaderName2}=await Promise.resolve().then(() => (init_team_manager(),exports_team_manager)),teamsDir=join39(process.env.HOME??"/root",".claude","teams"),teams=readdirSync10(teamsDir);for(let team of teams)try{let configPath2=join39(teamsDir,team,"config.json"),raw=readFileSync22(configPath2,"utf-8"),config=JSON.parse(raw);if(config.leadAgentId?.startsWith("team-lead@")){let actualLeader=await resolveLeaderName2(team),sanitized=sanitizeTeamName(team);config.leadAgentId=`${sanitizeTeamName(actualLeader)}@${sanitized}`,writeFileSync14(configPath2,JSON.stringify(config,null,2)),console.log(`[reconcile] Updated leadAgentId for team "${team}": ${config.leadAgentId}`)}}catch{}}catch{}}async function launchInsideTmux(windowName,workspaceDir,systemPromptFile,leaderName){let sessionId=randomUUID5(),suffix=Date.now().toString(36).slice(-4),currentWindowName=`${windowName}-${suffix}`;await executeTmux2(`rename-window ${shellQuote(currentWindowName)}`),await ensureNativeTeamForLeader(currentWindowName,workspaceDir,sessionId);let cmd=buildClaudeCommand2(currentWindowName,systemPromptFile||void 0,leaderName,sessionId,!1),{execSync:execSyncCmd}=__require("child_process");execSyncCmd(cmd,{stdio:"inherit",cwd:workspaceDir})}async function sessionCommand(options={}){await reconcileStaleSpawns(),await reconcileLeaderConfigs();let workspaceDir=options.dir??process.cwd(),sessionName=options.name??sanitizeWindowName(basename6(workspaceDir));try{let windowName=await deriveWindowName(sessionName,workspaceDir,options.team),leaderName=await resolveSessionLeaderName(windowName);if(options.reset)await handleReset(sessionName,windowName);let session=await findSessionByName(sessionName),systemPromptFile=getAgentsFilePath();if(!systemPromptFile)if(await esm_default4({message:"No agent found in this directory. Scaffold one?",default:!0}))scaffoldAgentFiles(workspaceDir),systemPromptFile=join38(workspaceDir,"AGENTS.md"),console.log("Created SOUL.md, HEARTBEAT.md, and AGENTS.md");else console.error("AGENTS.md required. Run `genie` again to scaffold."),process.exit(1);if(!session)await createSession2(sessionName,windowName,workspaceDir,systemPromptFile,leaderName),attachToWindow(sessionName,windowName);else if(process.env.TMUX)await launchInsideTmux(windowName,workspaceDir,systemPromptFile,leaderName);else console.log(`Session "${sessionName}" already exists`),await focusTeamWindow(sessionName,windowName,workspaceDir,systemPromptFile,leaderName),attachToWindow(sessionName,windowName)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}var init_session=__esm(()=>{init_esm14();init_agent_registry();init_agent_registry();init_claude_native_teams();init_executor_registry();init_team_lead_command();init_tmux();init_templates()});var exports_should_resume={};__export(exports_should_resume,{shouldResume:()=>shouldResume,emitBootPassEvent:()=>emitBootPassEvent,classifyBootPass:()=>classifyBootPass,bootPassEventType:()=>bootPassEventType,bootPassDecisions:()=>bootPassDecisions,BOOT_PASS_CONCURRENCY_CAP:()=>BOOT_PASS_CONCURRENCY_CAP});async function readAgentResumeRow(agentId){return(await(await getConnection())`
|
|
1550
1550
|
SELECT
|
|
1551
1551
|
a.id,
|
|
1552
1552
|
a.auto_resume,
|
|
@@ -1610,7 +1610,7 @@ Stopping inbox watcher...`),stopInboxWatcher2(handle),process.exit(0)};process.o
|
|
|
1610
1610
|
SELECT decision, timeout_at FROM approvals WHERE id = ${approvalId}
|
|
1611
1611
|
`;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((resolve6)=>{let resolved=!1,listener=null,pollTimer=null,finish=(decision)=>{if(resolved)return;if(resolved=!0,listener)listener.unlisten().catch(()=>{});if(pollTimer)clearInterval(pollTimer);resolve6(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 readFileSync22}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=readFileSync22(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(`
|
|
1612
1612
|
`).filter((l)=>l.trim()).slice(-8).join(`
|
|
1613
|
-
`);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 createHash5}from"crypto";import{existsSync as existsSync35}from"fs";import{dirname as
|
|
1613
|
+
`);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 createHash5}from"crypto";import{existsSync as existsSync35}from"fs";import{dirname as dirname10}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 createHash5("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 existsSync35(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:dirname10(currentDir)}}).trim();return normalizeGitPath(dirname10(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`
|
|
1614
1614
|
SELECT * FROM tasks
|
|
1615
1615
|
WHERE wish_file = ${wishFile} AND repo_path = ${repoPath} AND parent_id IS NULL
|
|
1616
1616
|
LIMIT 1
|
|
@@ -2114,7 +2114,7 @@ ${body}`;writeFileSync14(filePath,output,"utf-8")}function serializeSdkConfig(sd
|
|
|
2114
2114
|
AND a.team = ${teamName}
|
|
2115
2115
|
AND e.state NOT IN ('terminated', 'done', 'error')
|
|
2116
2116
|
LIMIT 1
|
|
2117
|
-
`;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 dirname11=sp.dirname(file),basename7=sp.basename(file),parent=this.fsw._getWatchedDir(dirname11),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(dirname11,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((resolve8,reject)=>{if(!stream)return reject();stream.once(STR_END,()=>{if(this.fsw.closed){stream=void 0;return}let wasThrottled=throttler?throttler.clear():!1;if(resolve8(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,isForeignKeyViolation:()=>isForeignKeyViolation,handleFileChange:()=>handleFileChange,extractSessionInfo:()=>extractSessionInfo,createJsonlWatcher:()=>createJsonlWatcher});import{homedir as homedir32}from"os";import{basename as basename8,isAbsolute as isAbsolute3,join as join51,resolve as resolve9}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")}async function loadOffsets(sql){try{let rows=await sql`SELECT id, last_ingested_offset FROM sessions WHERE last_ingested_offset > 0`;for(let row of rows)offsetCache.set(row.id,row.last_ingested_offset)}catch{}}function extractSessionInfo(filePath){if(!filePath.endsWith(".jsonl"))return null;let sessionId=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 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);let workerMap=await deps.buildWorkerMap(sql),result2=await deps.ingestFileFull(sql,info.sessionId,filePath,info.projectPath,storedOffset,{parentSessionId:info.parentSessionId,isSubagent:info.isSubagent,workerMap});offsetCache.set(info.sessionId,result2.newOffset)}catch(err){let message=err instanceof Error?err.message:String(err);if(isForeignKeyViolation(err))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}`);else deps.logError(`[filewatch] error ingesting ${filePath} at offset ${storedOffset}: ${message}`)}finally{deps.setLiveWorkPending(!1)}}function shouldIgnoreWatchPath(path3,stats2){return stats2?.isFile()===!0&&!path3.endsWith(".jsonl")}function normalizeWatchEventPath(claudeDir,filePath){return isAbsolute3(filePath)?filePath:resolve9(claudeDir,filePath)}function scheduleFileChange(filePath,sql){if(!filePath.endsWith(".jsonl"))return;let existing=debounceTimers.get(filePath);if(existing)clearTimeout(existing);debounceTimers.set(filePath,setTimeout(()=>{debounceTimers.delete(filePath),handleFileChange(filePath,sql).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=join51(process.env.CLAUDE_CONFIG_DIR??join51(homedir32(),".claude"),"projects");await loadOffsets(sql);try{return watcher=createJsonlWatcher(claudeDir,(fullPath)=>scheduleFileChange(fullPath,sql)),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_session_capture();offsetCache=new Map,debounceTimers=new Map,unrecoverableSessions=new Set;defaultDeps4={buildWorkerMap,ingestFileFull,setLiveWorkPending,logError:(msg)=>console.error(msg)}});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 appendFileSync3,mkdirSync as mkdirSync16}from"fs";import{homedir as homedir33}from"os";import{join as join52}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 join52(process.env.GENIE_HOME??join52(homedir33(),".genie"),"logs")}function getLogFile(){return join52(getLogDir2(),"scheduler.log")}function logToFile(entry2){let logDir=getLogDir2();mkdirSync16(logDir,{recursive:!0});let enriched=entry2.trace_id?entry2:withAmbientTraceId(entry2);appendFileSync3(getLogFile(),`${JSON.stringify(enriched)}
|
|
2117
|
+
`;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,basename7=this._isDirent?dirent.name:dirent;try{let fullPath=presolve(pjoin(path3,basename7));entry2={path:prelative(this._root,fullPath),fullPath,basename:basename7},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),basename8=sp.basename(path3);this.fsw._getWatchedDir(directory).add(basename8);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(basename8)?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 dirname12=sp.dirname(file),basename8=sp.basename(file),parent=this.fsw._getWatchedDir(dirname12),prevStats=stats2;if(parent.has(basename8))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(dirname12,basename8)}else if(parent.has(basename8)){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((resolve8,reject)=>{if(!stream)return reject();stream.once(STR_END,()=>{if(this.fsw.closed){stream=void 0;return}let wasThrottled=throttler?throttler.clear():!1;if(resolve8(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,isForeignKeyViolation:()=>isForeignKeyViolation,handleFileChange:()=>handleFileChange,extractSessionInfo:()=>extractSessionInfo,createJsonlWatcher:()=>createJsonlWatcher});import{homedir as homedir32}from"os";import{basename as basename9,isAbsolute as isAbsolute3,join as join51,resolve as resolve9}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")}async function loadOffsets(sql){try{let rows=await sql`SELECT id, last_ingested_offset FROM sessions WHERE last_ingested_offset > 0`;for(let row of rows)offsetCache.set(row.id,row.last_ingested_offset)}catch{}}function extractSessionInfo(filePath){if(!filePath.endsWith(".jsonl"))return null;let sessionId=basename9(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 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);let workerMap=await deps.buildWorkerMap(sql),result2=await deps.ingestFileFull(sql,info.sessionId,filePath,info.projectPath,storedOffset,{parentSessionId:info.parentSessionId,isSubagent:info.isSubagent,workerMap});offsetCache.set(info.sessionId,result2.newOffset)}catch(err){let message=err instanceof Error?err.message:String(err);if(isForeignKeyViolation(err))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}`);else deps.logError(`[filewatch] error ingesting ${filePath} at offset ${storedOffset}: ${message}`)}finally{deps.setLiveWorkPending(!1)}}function shouldIgnoreWatchPath(path3,stats2){return stats2?.isFile()===!0&&!path3.endsWith(".jsonl")}function normalizeWatchEventPath(claudeDir,filePath){return isAbsolute3(filePath)?filePath:resolve9(claudeDir,filePath)}function scheduleFileChange(filePath,sql){if(!filePath.endsWith(".jsonl"))return;let existing=debounceTimers.get(filePath);if(existing)clearTimeout(existing);debounceTimers.set(filePath,setTimeout(()=>{debounceTimers.delete(filePath),handleFileChange(filePath,sql).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=join51(process.env.CLAUDE_CONFIG_DIR??join51(homedir32(),".claude"),"projects");await loadOffsets(sql);try{return watcher=createJsonlWatcher(claudeDir,(fullPath)=>scheduleFileChange(fullPath,sql)),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_session_capture();offsetCache=new Map,debounceTimers=new Map,unrecoverableSessions=new Set;defaultDeps4={buildWorkerMap,ingestFileFull,setLiveWorkPending,logError:(msg)=>console.error(msg)}});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 appendFileSync3,mkdirSync as mkdirSync16}from"fs";import{homedir as homedir33}from"os";import{join as join52}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 join52(process.env.GENIE_HOME??join52(homedir33(),".genie"),"logs")}function getLogFile(){return join52(getLogDir2(),"scheduler.log")}function logToFile(entry2){let logDir=getLogDir2();mkdirSync16(logDir,{recursive:!0});let enriched=entry2.trace_id?entry2:withAmbientTraceId(entry2);appendFileSync3(getLogFile(),`${JSON.stringify(enriched)}
|
|
2118
2118
|
`)}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((resolve10)=>setTimeout(resolve10,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())`
|
|
2119
2119
|
SELECT a.id AS agent_id, e.claude_session_id
|
|
2120
2120
|
FROM agents a
|
|
@@ -2346,7 +2346,7 @@ ${body}`;writeFileSync14(filePath,output,"utf-8")}function serializeSdkConfig(sd
|
|
|
2346
2346
|
WHERE t.status <> ALL(${sql.array([...EXEMPT_TEAM_STATUSES])})
|
|
2347
2347
|
ORDER BY t.updated_at DESC
|
|
2348
2348
|
LIMIT 500
|
|
2349
|
-
`).map((r)=>({team_name:r.team_name,status:r.status,worktree_path:r.worktree_path,base_branch:r.base_branch,lead_agent_id:r.lead_agent_id,lead_state:r.lead_state,last_executor_active_ms:r.last_executor_active_ms===null?null:Number(r.last_executor_active_ms),now_ms:Number(r.now_ms)}))},queryFn=opts?.query??defaultQuery,isIdlePastThreshold=(row)=>{if(row.last_executor_active_ms===null)return!0;return row.now_ms-row.last_executor_active_ms>thresholdMs},probeOne2=async(row)=>{let probe=await gitProbe(row);if(!probe.ok||probe.branch_ahead_count<=0)return null;return{row,branchAheadCount:probe.branch_ahead_count,lastCommitMs:probe.last_commit_ms}};return{id:"rot.team-unpushed-orphaned-worktree",version,riskClass:"low",async query(){let idle=(await queryFn()).filter(isIdlePastThreshold),batch=idle.slice(0,maxTeamsPerTick),idleUnprobed=idle.length-batch.length,stalled=[];for(let row of batch){let result2=await probeOne2(row);if(result2!==null)stalled.push(result2)}return{stalled,idleUnprobed,idleMinutes}},shouldFire(state){return state.stalled.length>0},render(state){let first=state.stalled[0],row=first.row,minutesSinceActive=row.last_executor_active_ms===null?null:Math.floor((row.now_ms-row.last_executor_active_ms)/60000),lastExecutorActiveIso=row.last_executor_active_ms===null?null:new Date(row.last_executor_active_ms).toISOString(),lastCommitIso=first.lastCommitMs===null?null:new Date(first.lastCommitMs).toISOString(),totalStalledTeams=state.stalled.length+state.idleUnprobed;return{type:"rot.detected",subject:row.team_name,payload:{pattern_id:"pattern-9-team-unpushed-orphaned-worktree",entity_id:row.team_name,observed_state_json:{team_name:row.team_name,team_status:row.status,worktree_path:row.worktree_path,base_branch:row.base_branch??"",branch_ahead_count:first.branchAheadCount,last_commit_at:lastCommitIso,last_executor_active_at:lastExecutorActiveIso,minutes_since_active:minutesSinceActive,threshold_minutes:state.idleMinutes,lead_agent_id:row.lead_agent_id,lead_state:row.lead_state,total_stalled_teams:totalStalledTeams}}}}}}var LIVE_EXECUTOR_STATES,EXEMPT_TEAM_STATUSES,DEFAULT_IDLE_MINUTES2=10,DEFAULT_MAX_TEAMS_PER_TICK=32,DEFAULT_GIT_TIMEOUT_MS=3000;var init_pattern_9_team_unpushed_orphaned_worktree=__esm(()=>{init_db();init_detectors();LIVE_EXECUTOR_STATES=["running","spawning"],EXEMPT_TEAM_STATUSES=["done","blocked","archived"];registerDetector(createTeamUnpushedOrphanedWorktreeDetector())});import{readdir as readdir9,stat as stat8}from"fs/promises";import{basename as
|
|
2349
|
+
`).map((r)=>({team_name:r.team_name,status:r.status,worktree_path:r.worktree_path,base_branch:r.base_branch,lead_agent_id:r.lead_agent_id,lead_state:r.lead_state,last_executor_active_ms:r.last_executor_active_ms===null?null:Number(r.last_executor_active_ms),now_ms:Number(r.now_ms)}))},queryFn=opts?.query??defaultQuery,isIdlePastThreshold=(row)=>{if(row.last_executor_active_ms===null)return!0;return row.now_ms-row.last_executor_active_ms>thresholdMs},probeOne2=async(row)=>{let probe=await gitProbe(row);if(!probe.ok||probe.branch_ahead_count<=0)return null;return{row,branchAheadCount:probe.branch_ahead_count,lastCommitMs:probe.last_commit_ms}};return{id:"rot.team-unpushed-orphaned-worktree",version,riskClass:"low",async query(){let idle=(await queryFn()).filter(isIdlePastThreshold),batch=idle.slice(0,maxTeamsPerTick),idleUnprobed=idle.length-batch.length,stalled=[];for(let row of batch){let result2=await probeOne2(row);if(result2!==null)stalled.push(result2)}return{stalled,idleUnprobed,idleMinutes}},shouldFire(state){return state.stalled.length>0},render(state){let first=state.stalled[0],row=first.row,minutesSinceActive=row.last_executor_active_ms===null?null:Math.floor((row.now_ms-row.last_executor_active_ms)/60000),lastExecutorActiveIso=row.last_executor_active_ms===null?null:new Date(row.last_executor_active_ms).toISOString(),lastCommitIso=first.lastCommitMs===null?null:new Date(first.lastCommitMs).toISOString(),totalStalledTeams=state.stalled.length+state.idleUnprobed;return{type:"rot.detected",subject:row.team_name,payload:{pattern_id:"pattern-9-team-unpushed-orphaned-worktree",entity_id:row.team_name,observed_state_json:{team_name:row.team_name,team_status:row.status,worktree_path:row.worktree_path,base_branch:row.base_branch??"",branch_ahead_count:first.branchAheadCount,last_commit_at:lastCommitIso,last_executor_active_at:lastExecutorActiveIso,minutes_since_active:minutesSinceActive,threshold_minutes:state.idleMinutes,lead_agent_id:row.lead_agent_id,lead_state:row.lead_state,total_stalled_teams:totalStalledTeams}}}}}}var LIVE_EXECUTOR_STATES,EXEMPT_TEAM_STATUSES,DEFAULT_IDLE_MINUTES2=10,DEFAULT_MAX_TEAMS_PER_TICK=32,DEFAULT_GIT_TIMEOUT_MS=3000;var init_pattern_9_team_unpushed_orphaned_worktree=__esm(()=>{init_db();init_detectors();LIVE_EXECUTOR_STATES=["running","spawning"],EXEMPT_TEAM_STATUSES=["done","blocked","archived"];registerDetector(createTeamUnpushedOrphanedWorktreeDetector())});import{readdir as readdir9,stat as stat8}from"fs/promises";import{basename as basename10,join as join53}from"path";async function defaultListTranscripts(){let entries;try{entries=await readdir9(DEFAULT_SEARCH_ROOT)}catch{return[]}let out=[];for(let entry2 of entries){if(!entry2.startsWith(DEFAULT_SEARCH_PREFIX))continue;await walkForOutputFiles(join53(DEFAULT_SEARCH_ROOT,entry2),out,DEFAULT_WALK_DEPTH)}return out}async function walkForOutputFiles(dir,sink,depthBudget){if(depthBudget<=0)return;let dirents;try{dirents=await readdir9(dir,{withFileTypes:!0})}catch{return}for(let dirent of dirents){let full=join53(dir,dirent.name);if(dirent.isDirectory()){await walkForOutputFiles(full,sink,depthBudget-1);continue}if(!dirent.isFile()||!dirent.name.endsWith(".output"))continue;try{let st=await stat8(full);sink.push({agent_id:basename10(dirent.name,".output"),transcript_path:full,size_bytes:st.size,mtime_ms:st.mtimeMs})}catch{}}}async function defaultCheckAgentIds(ids){if(ids.length===0)return new Set;let rows=await(await getConnection())`
|
|
2350
2350
|
SELECT id FROM agents WHERE id = ANY(${ids})
|
|
2351
2351
|
`;return new Set(rows.map((r)=>r.id))}function makeAgentToolBypassDetector(deps){let windowMs=deps.activeWindowMs??DEFAULT_ACTIVE_WINDOW_MS,maxOrphans=deps.maxOrphansPerEvent??DEFAULT_MAX_ORPHANS_PER_EVENT;return{id:"rot.agent-tool-bypass",version:"1.0.0",riskClass:"medium",async query(){let nowMs=deps.now(),active=(await deps.listTranscripts()).filter((t)=>nowMs-t.mtime_ms<=windowMs),ids=active.map((t)=>t.agent_id),known=ids.length===0?new Set:await deps.checkAgentIds(ids),orphans=[];for(let t of active){if(known.has(t.agent_id))continue;orphans.push({agent_id:t.agent_id,transcript_path:t.transcript_path,size_bytes:t.size_bytes,mtime_iso:new Date(t.mtime_ms).toISOString()})}return{orphans,scanned_count:active.length}},shouldFire(state){return state.orphans.length>0},render(state){let head=state.orphans.slice(0,maxOrphans),first=head[0];return{type:"rot.detected",subject:first?.agent_id??"unknown",payload:{pattern_id:"pattern-10-agent-tool-bypass",entity_id:first?.agent_id??"unknown",observed_state_json:{agent_id:first?.agent_id??"unknown",transcript_path:first?.transcript_path??"",size_bytes:first?.size_bytes??0,mtime_iso:first?.mtime_iso??"",detected_at:new Date(deps.now()).toISOString(),orphan_count:state.orphans.length,scanned_count:state.scanned_count,agent_ids:head.map((o)=>o.agent_id),transcript_paths:head.map((o)=>o.transcript_path),sizes_bytes:head.map((o)=>o.size_bytes)}}}}}}var DEFAULT_ACTIVE_WINDOW_MS=600000,DEFAULT_MAX_ORPHANS_PER_EVENT=32,DEFAULT_SEARCH_ROOT="/tmp",DEFAULT_SEARCH_PREFIX="claude-",DEFAULT_WALK_DEPTH=4,agentToolBypassDetector;var init_pattern_10_agent_tool_bypass=__esm(()=>{init_db();init_detectors();agentToolBypassDetector=makeAgentToolBypassDetector({listTranscripts:defaultListTranscripts,checkAgentIds:defaultCheckAgentIds,now:()=>Date.now()});registerDetector(agentToolBypassDetector)});var exports_built_in={};var init_built_in=__esm(()=>{init_pattern_1_backfill_no_worktree();init_pattern_4_duplicate_agents();init_pattern_5_zombie_team_lead();init_pattern_2_team_ls_drift();init_pattern_3_anchor_orphan();init_pattern_6_subagent_cascade();init_pattern_7_dispatch_silent_drop();init_pattern_8_session_reuse_ghost();init_pattern_9_team_unpushed_orphaned_worktree();init_pattern_10_agent_tool_bypass()});var exports_detector_scheduler={};__export(exports_detector_scheduler,{start:()=>start,DEFAULT_TICK_INTERVAL_MS:()=>DEFAULT_TICK_INTERVAL_MS,DEFAULT_JITTER_MS:()=>DEFAULT_JITTER_MS,DEFAULT_FIRE_BUDGET:()=>DEFAULT_FIRE_BUDGET,DEFAULT_DETECTOR_BUDGETS:()=>DEFAULT_DETECTOR_BUDGETS});function start(options={}){let tickIntervalMs=options.tickIntervalMs??DEFAULT_TICK_INTERVAL_MS,jitterMs=options.jitterMs??DEFAULT_JITTER_MS,defaultBudget=options.defaultFireBudget??DEFAULT_FIRE_BUDGET,budgets={...DEFAULT_DETECTOR_BUDGETS,...options.fireBudgets??{}},now=options.now??(()=>Date.now()),setTimeoutFn=options.setTimeoutFn??((fn,ms)=>setTimeout(fn,ms)),clearTimeoutFn=options.clearTimeoutFn??((handle)=>{clearTimeout(handle)}),resolveDetectors=options.detectorSource??listDetectors,emit2=options.emitFn??emitEvent,state={ticks:0,fires:0,disables:0,budgetBuckets:{}},disabledBuckets=new Set,stopped=!1,currentTimer=null,tickInFlight=null;async function runTick(){if(stopped)return;state.ticks++;let detectors=resolveDetectors();for(let detector of detectors)await runOneDetector(detector)}async function safeCall(fn){try{return await fn()}catch{return null}}function emitFire(detector,event){emit2(event.type,event.payload,{detector_version:detector.version,source_subsystem:"detector-scheduler",entity_id:event.subject??detector.id,agent:process.env.GENIE_AGENT_NAME??"detector-scheduler"}),state.fires++}function emitDisable(detector,budget,current,bucketStart){state.disables++,emit2("detector.disabled",{detector_id:detector.id,cause:"fire_budget_exceeded",budget,fire_count:current,bucket_end_ts:new Date(bucketStart+HOUR_MS).toISOString()},{detector_version:detector.version,source_subsystem:"detector-scheduler",entity_id:detector.id,severity:"warn",agent:process.env.GENIE_AGENT_NAME??"detector-scheduler"})}async function runOneDetector(detector){let bucketStart=Math.floor(now()/HOUR_MS)*HOUR_MS,bucketKey=`${detector.id}:${bucketStart}`,budget=budgets[detector.id]??defaultBudget;if(disabledBuckets.has(bucketKey))return;let result2=await safeCall(()=>detector.query());if(result2===null)return;if(!await safeCall(()=>detector.shouldFire(result2)))return;let current=(state.budgetBuckets[bucketKey]??0)+1;state.budgetBuckets[bucketKey]=current;let event=await safeCall(()=>detector.render(result2));if(event===null)return;if(emitFire(detector,event),current>=budget&&!disabledBuckets.has(bucketKey))disabledBuckets.add(bucketKey),emitDisable(detector,budget,current,bucketStart)}function scheduleNext(){if(stopped)return;let jitter=jitterMs>0?Math.floor((Math.random()*2-1)*jitterMs):0,delay=Math.max(0,tickIntervalMs+jitter);currentTimer=setTimeoutFn(()=>{tickInFlight=runTick().finally(()=>{tickInFlight=null,scheduleNext()})},delay)}return scheduleNext(),{stop(){if(stopped)return;if(stopped=!0,currentTimer)clearTimeoutFn(currentTimer),currentTimer=null},async tickNow(){if(tickInFlight)await tickInFlight;await runTick()},stats(){return{...state,budgetBuckets:{...state.budgetBuckets}}}}}var DEFAULT_TICK_INTERVAL_MS=60000,DEFAULT_JITTER_MS=5000,DEFAULT_FIRE_BUDGET=100,DEFAULT_DETECTOR_BUDGETS,HOUR_MS=3600000;var init_detector_scheduler=__esm(()=>{init_detectors();init_emit();init_pattern_2_team_ls_drift();DEFAULT_DETECTOR_BUDGETS=Object.freeze({"rot.team-ls-drift":20,"rot.backfill-no-worktree":40})});var exports_executor_read={};__export(exports_executor_read,{stopExecutorReadEndpoint:()=>stopExecutorReadEndpoint,startExecutorReadEndpoint:()=>startExecutorReadEndpoint,readExecutorState:()=>readExecutorState,isExecutorReadEndpointRunning:()=>isExecutorReadEndpointRunning,getExecutorReadPort:()=>getExecutorReadPort});async function readExecutorState(id,sql){let rows=await(sql??await getConnection())`SELECT state, outcome, closed_at FROM executors WHERE id = ${id} LIMIT 1`;if(rows.length===0)return null;let row=rows[0];return{state:row.state,outcome:row.outcome??null,closed_at:row.closed_at==null?null:row.closed_at instanceof Date?row.closed_at.toISOString():row.closed_at}}function getExecutorReadPort(){let envPort=process.env.GENIE_EXECUTOR_READ_PORT;if(envPort){let parsed=Number.parseInt(envPort,10);if(!Number.isNaN(parsed)&&parsed>0&&parsed<65536)return parsed}return getActivePort()+2}async function handleStateRoute(id){if(!UUID_RE.test(id))return Response.json({error:"invalid executor id"},{status:400});try{let reply=await readExecutorState(id);if(!reply)return Response.json({error:"not found"},{status:404});return Response.json(reply,{headers:{"Cache-Control":"no-store"}})}catch(err){let msg=err instanceof Error?err.message:String(err);return Response.json({error:msg},{status:500})}}async function routeRequest(req,port){let url=new URL(req.url);if(req.method==="GET"&&url.pathname==="/health")return Response.json({status:"ok",port});if(req.method!=="GET")return new Response("Method Not Allowed",{status:405});let match=ROUTE_RE.exec(url.pathname);if(!match)return new Response("Not Found",{status:404});return handleStateRoute(match[1])}async function startExecutorReadEndpoint(){if(server2)return!0;let port=getExecutorReadPort();try{return server2=Bun.serve({port,hostname:"127.0.0.1",fetch:(req)=>routeRequest(req,port)}),!0}catch(err){let message=err instanceof Error?err.message:String(err);if(message.includes("EADDRINUSE")||message.includes("address already in use"))console.warn(`Executor read endpoint: port ${port} already in use \u2014 skipping`);else console.warn(`Executor read endpoint: failed to start on port ${port}: ${message}`);return!1}}async function stopExecutorReadEndpoint(){if(server2)await server2.stop(!0),server2=null}function isExecutorReadEndpointRunning(){return server2!==null}var server2=null,UUID_RE,ROUTE_RE;var init_executor_read=__esm(()=>{init_db();UUID_RE=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,ROUTE_RE=/^\/executors\/([^/]+)\/state\/?$/});var exports_omni_approval_handler={};__export(exports_omni_approval_handler,{startOmniApprovalHandler:()=>startOmniApprovalHandler});class OmniApprovalHandler{nc=null;subs=[];sc=import_nats2.StringCodec();permissions;natsUrl;approveTokens;denyTokens;constructor(config){this.permissions=config.permissions,this.natsUrl=config.natsUrl??"localhost:4222",this.approveTokens=(config.permissions.approveTokens??DEFAULT_APPROVE_TOKENS).map((t)=>t.toLowerCase()),this.denyTokens=(config.permissions.denyTokens??DEFAULT_DENY_TOKENS).map((t)=>t.toLowerCase())}async start(){let{omniChat,omniInstance}=this.permissions;if(!omniChat||!omniInstance)return;this.nc=await import_nats2.connect({servers:this.natsUrl});let messageTopic=`omni.message.${omniInstance}.>`,msgSub=this.nc.subscribe(messageTopic);this.subs.push(msgSub),this.processMessages(msgSub);let eventSub=this.nc.subscribe("omni.event.>");this.subs.push(eventSub),this.processEvents(eventSub),handlerInstance=this,console.log(`[omni-approval] Listening for approval replies on ${messageTopic}`)}async stop(){for(let sub of this.subs)sub.unsubscribe();if(this.subs=[],this.nc)await this.nc.close(),this.nc=null;if(handlerInstance===this)handlerInstance=null}async processMessages(sub){for await(let msg of sub)try{let data=JSON.parse(this.sc.decode(msg.data));if((data.chatId??this.extractChatIdFromSubject(msg.subject))!==this.permissions.omniChat)continue;if(data.content)await this.handleTextReply(data.content,data.sender??"whatsapp-user")}catch{}}async processEvents(sub){for await(let msg of sub)try{let data=JSON.parse(this.sc.decode(msg.data));if(data.type!=="reaction")continue;if(data.chatId!==this.permissions.omniChat||data.instanceId!==this.permissions.omniInstance)continue;if(data.emoji&&data.messageId)await this.handleReaction(data.emoji,data.messageId,data.sender??"whatsapp-user")}catch{}}extractChatIdFromSubject(subject){let parts=subject.split(".");if(parts.length>=4)return parts.slice(3).join(".");return}async handleTextReply(content,sender){let normalized=content.trim().toLowerCase();if(!normalized)return!1;let decision=null;if(this.approveTokens.includes(normalized))decision="allow";else if(this.denyTokens.includes(normalized))decision="deny";if(!decision)return!1;let pending=await listPendingApprovals();if(pending.length===0)return!1;let oldest=pending[0],resolved=await resolveApproval(oldest.id,decision,sender);if(resolved)console.log(`[omni-approval] Resolved ${oldest.id} as ${decision} by ${sender} (text: "${normalized}")`);return resolved}async handleReaction(emoji,messageId,sender){let decision=null;if(DEFAULT_APPROVE_REACTIONS.includes(emoji))decision="allow";else if(DEFAULT_DENY_REACTIONS.includes(emoji))decision="deny";if(!decision)return!1;try{let sql=await getConnection(),[approval]=await sql`
|
|
2352
2352
|
SELECT id FROM approvals
|
|
@@ -2493,17 +2493,17 @@ ${queryContent}`;let{messages:queryMessages}=state.provider.runQuery({agentId:se
|
|
|
2493
2493
|
UPDATE omni_requests
|
|
2494
2494
|
SET status = 'pending', started_at = NULL, next_retry_at = ${nextRetry}
|
|
2495
2495
|
WHERE id = ${id}
|
|
2496
|
-
`}}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 existsSync43,mkdirSync as mkdirSync17,openSync as openSync4,readFileSync as readFileSync26,unlinkSync as unlinkSync9,writeSync}from"fs";import{dirname as
|
|
2496
|
+
`}}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 existsSync43,mkdirSync as mkdirSync17,openSync as openSync4,readFileSync as readFileSync26,unlinkSync as unlinkSync9,writeSync}from"fs";import{dirname as dirname13}from"path";function withTimeout2(p,ms,label){return new Promise((resolve10,reject)=>{let timer2=setTimeout(()=>reject(Error(`${label} timed out after ${ms}ms`)),ms);timer2.unref?.(),p.then((v)=>{clearTimeout(timer2),resolve10(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;sessions=new Map;messageQueue=[];recentMessageIds=new Map;idleCheckTimer=null;sc=import_nats3.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_nats3.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;this.executor.setNatsPublish((topic,payload)=>{nc.publish(topic,sc.encode(payload))})}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{mkdirSync17(dirname13(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(!existsSync43(path3))return;let stalePid=null;try{let raw=readFileSync26(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(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`
|
|
2497
2497
|
SELECT id FROM executors
|
|
2498
2498
|
WHERE ended_at IS NULL AND metadata->>'source' = 'omni'
|
|
2499
|
-
`,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);break;case"done":this.turnTracker.close(sessionKey2,payload.action),await this.handleTurnDone(sessionKey2);break;case"nudge":await this.handleTurnNudge(sessionKey2,payload.message);break;case"timeout":await this.handleTurnTimeout(sessionKey2);break}}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"),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");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");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:[message],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=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);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_nats3,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_claude_code2();init_claude_sdk2();import_nats3=__toESM(require_mod4(),1)});var exports_hook_socket={};__export(exports_hook_socket,{startHookSocket:()=>startHookSocket,defaultHookSocketPath:()=>defaultHookSocketPath});import{existsSync as existsSync44,unlinkSync as unlinkSync10}from"fs";import{mkdir as mkdir7}from"fs/promises";import{createServer,connect as netConnect}from"net";import{homedir as homedir35}from"os";import{dirname as dirname13,join as join55}from"path";function defaultHookSocketPath(){if(process.env.GENIE_HOOK_SOCK)return process.env.GENIE_HOOK_SOCK;let home=process.env.GENIE_HOME??join55(homedir35(),".genie");return join55(home,"hook.sock")}async function detectStaleAndCleanup(socketPath){if(!existsSync44(socketPath))return"clean";if(await new Promise((resolve10)=>{let probe=netConnect(socketPath),finish=(alive)=>{try{probe.destroy()}catch{}resolve10(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_BYTES)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((resolve10,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")resolve10(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_BYTES){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(){if(process.env.GENIE_WIDE_EMIT===void 0)process.env.GENIE_WIDE_EMIT="1";let socketPath=defaultHookSocketPath();await mkdir7(dirname13(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((resolve10,reject)=>{let onError=(err)=>{server3.off("listening",onListening),reject(err)},onListening=()=>{server3.off("error",onError),resolve10()};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((resolve10)=>{server3.close(()=>resolve10())}),existsSync44(socketPath))try{unlinkSync10(socketPath)}catch{}}}}var MAX_FRAME_BYTES=1048576;var init_hook_socket=__esm(()=>{init_hooks()});var exports_serve={};__export(exports_serve,{writeStoppingLockSync:()=>writeStoppingLockSync,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 spawnSync5}from"child_process";import{closeSync as closeSync5,existsSync as existsSync45,mkdirSync as mkdirSync18,openSync as openSync5,readFileSync as readFileSync27,unlinkSync as unlinkSync11,writeFileSync as writeFileSync16,writeSync as writeSync2}from"fs";import{homedir as homedir36}from"os";import{dirname as dirname14,join as join56}from"path";function genieHome3(){return process.env.GENIE_HOME??join56(homedir36(),".genie")}function servePidPath(){return join56(genieHome3(),"serve.pid")}function serveStartupStatusPath(){return join56(genieHome3(),"state",`serve-startup-${process.pid}-${Date.now()}.json`)}function readServePid(){let path3=servePidPath();if(!existsSync45(path3))return null;let raw=readFileSync27(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(!existsSync45(path3))return;try{let current=readServePid();if(current&¤t.pid!==process.pid)return;unlinkSync11(path3)}catch{}}function isProcessAlive(pid){try{return process.kill(pid,0),!0}catch{return!1}}function stoppingLockPath(){return join56(genieHome3(),"serve.stopping.lock")}function writeStoppingLockSync(ttlMs=STOPPING_LOCK_TTL_MS){mkdirSync18(genieHome3(),{recursive:!0}),writeFileSync16(stoppingLockPath(),String(Date.now()+ttlMs),"utf-8")}function clearStoppingLock(){try{unlinkSync11(stoppingLockPath())}catch{}}function isStoppingLockActive(){let path3=stoppingLockPath();if(!existsSync45(path3))return!1;let raw;try{raw=readFileSync27(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[join56(genieHome3(),"tui-tmux.conf")].find((p)=>existsSync45(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 "))spawnSync5(tmuxBin(),["-L","genie-tui","-f",tuiTmuxConf(),...getTuiQuitBindingArgs()],{stdio:"ignore"});else execSync10(tuiTmux(cmd),{stdio:"ignore"})}catch{}}function startTuiTmuxServer(){try{execSync10(tuiTmux(`has-session -t ${TUI_SESSION}`),{stdio:"ignore"});let panes2=execSync10(tuiTmux(`list-panes -t ${TUI_SESSION}:0 -F '#{pane_id}'`),{encoding:"utf-8"}).trim().split(`
|
|
2499
|
+
`,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);break;case"done":this.turnTracker.close(sessionKey2,payload.action),await this.handleTurnDone(sessionKey2);break;case"nudge":await this.handleTurnNudge(sessionKey2,payload.message);break;case"timeout":await this.handleTurnTimeout(sessionKey2);break}}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"),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");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");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:[message],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=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);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_nats3,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_claude_code2();init_claude_sdk2();import_nats3=__toESM(require_mod4(),1)});var exports_hook_socket={};__export(exports_hook_socket,{startHookSocket:()=>startHookSocket,defaultHookSocketPath:()=>defaultHookSocketPath});import{existsSync as existsSync44,unlinkSync as unlinkSync10}from"fs";import{mkdir as mkdir7}from"fs/promises";import{createServer,connect as netConnect}from"net";import{homedir as homedir35}from"os";import{dirname as dirname14,join as join55}from"path";function defaultHookSocketPath(){if(process.env.GENIE_HOOK_SOCK)return process.env.GENIE_HOOK_SOCK;let home=process.env.GENIE_HOME??join55(homedir35(),".genie");return join55(home,"hook.sock")}async function detectStaleAndCleanup(socketPath){if(!existsSync44(socketPath))return"clean";if(await new Promise((resolve10)=>{let probe=netConnect(socketPath),finish=(alive)=>{try{probe.destroy()}catch{}resolve10(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_BYTES)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((resolve10,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")resolve10(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_BYTES){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(){if(process.env.GENIE_WIDE_EMIT===void 0)process.env.GENIE_WIDE_EMIT="1";let socketPath=defaultHookSocketPath();await mkdir7(dirname14(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((resolve10,reject)=>{let onError=(err)=>{server3.off("listening",onListening),reject(err)},onListening=()=>{server3.off("error",onError),resolve10()};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((resolve10)=>{server3.close(()=>resolve10())}),existsSync44(socketPath))try{unlinkSync10(socketPath)}catch{}}}}var MAX_FRAME_BYTES=1048576;var init_hook_socket=__esm(()=>{init_hooks()});var exports_serve={};__export(exports_serve,{writeStoppingLockSync:()=>writeStoppingLockSync,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 spawnSync5}from"child_process";import{closeSync as closeSync5,existsSync as existsSync45,mkdirSync as mkdirSync18,openSync as openSync5,readFileSync as readFileSync27,unlinkSync as unlinkSync11,writeFileSync as writeFileSync16,writeSync as writeSync2}from"fs";import{homedir as homedir36}from"os";import{dirname as dirname15,join as join56}from"path";function genieHome3(){return process.env.GENIE_HOME??join56(homedir36(),".genie")}function servePidPath(){return join56(genieHome3(),"serve.pid")}function serveStartupStatusPath(){return join56(genieHome3(),"state",`serve-startup-${process.pid}-${Date.now()}.json`)}function readServePid(){let path3=servePidPath();if(!existsSync45(path3))return null;let raw=readFileSync27(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(!existsSync45(path3))return;try{let current=readServePid();if(current&¤t.pid!==process.pid)return;unlinkSync11(path3)}catch{}}function isProcessAlive(pid){try{return process.kill(pid,0),!0}catch{return!1}}function stoppingLockPath(){return join56(genieHome3(),"serve.stopping.lock")}function writeStoppingLockSync(ttlMs=STOPPING_LOCK_TTL_MS){mkdirSync18(genieHome3(),{recursive:!0}),writeFileSync16(stoppingLockPath(),String(Date.now()+ttlMs),"utf-8")}function clearStoppingLock(){try{unlinkSync11(stoppingLockPath())}catch{}}function isStoppingLockActive(){let path3=stoppingLockPath();if(!existsSync45(path3))return!1;let raw;try{raw=readFileSync27(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[join56(genieHome3(),"tui-tmux.conf")].find((p)=>existsSync45(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 "))spawnSync5(tmuxBin(),["-L","genie-tui","-f",tuiTmuxConf(),...getTuiQuitBindingArgs()],{stdio:"ignore"});else execSync10(tuiTmux(cmd),{stdio:"ignore"})}catch{}}function startTuiTmuxServer(){try{execSync10(tuiTmux(`has-session -t ${TUI_SESSION}`),{stdio:"ignore"});let panes2=execSync10(tuiTmux(`list-panes -t ${TUI_SESSION}:0 -F '#{pane_id}'`),{encoding:"utf-8"}).trim().split(`
|
|
2500
2500
|
`);if(panes2.length>=2){try{execSync10(tuiTmux(`respawn-pane -k -t ${panes2[1]} 'cat'`),{stdio:"ignore"})}catch{}return{leftPane:panes2[0],rightPane:panes2[1]}}let cols2=Number.parseInt(execSync10(tuiTmux(`display-message -t ${TUI_SESSION}:0 -p '#{window_width}'`),{encoding:"utf-8"}).trim(),10)||120;execSync10(tuiTmux(`split-window -h -t ${TUI_SESSION}:0 -l ${cols2-NAV_WIDTH-1}`),{stdio:"ignore"});let refreshed=execSync10(tuiTmux(`list-panes -t ${TUI_SESSION}:0 -F '#{pane_id}'`),{encoding:"utf-8"}).trim().split(`
|
|
2501
2501
|
`);applyTuiStyle(),setupTuiKeybindings();try{execSync10(tuiTmux(`select-pane -t ${refreshed[0]}`),{stdio:"ignore"})}catch{}return{leftPane:refreshed[0],rightPane:refreshed[1]||refreshed[0]}}catch{}let cols=120;execSync10(tuiTmux(`new-session -d -s ${TUI_SESSION} -x ${cols} -y ${40}`),{stdio:"ignore"}),execSync10(tuiTmux(`split-window -h -t ${TUI_SESSION}:0 -l ${cols-NAV_WIDTH-1}`),{stdio:"ignore"});let panes=execSync10(tuiTmux(`list-panes -t ${TUI_SESSION}:0 -F '#{pane_id}'`),{encoding:"utf-8"}).trim().split(`
|
|
2502
2502
|
`);applyTuiStyle(),setupTuiKeybindings();try{execSync10(tuiTmux(`select-pane -t ${panes[0]}`),{stdio:"ignore"})}catch{}return{leftPane:panes[0],rightPane:panes[1]||panes[0]}}function sendTuiLaunchScript(leftPane,rightPane,workspaceRoot){let home=genieHome3(),bunPath=process.execPath||"bun",genieBin=process.argv[1]||"genie",scriptPath=join56(home,"tui-launch.sh"),logsDir=join56(home,"logs"),crashLog=join56(logsDir,"tui-crash.log"),envVars=["GENIE_TUI_PANE=left",`GENIE_TUI_RIGHT=${rightPane}`];if(workspaceRoot)envVars.push(`GENIE_TUI_WORKSPACE=${workspaceRoot}`);let content=["#!/bin/sh",`mkdir -p '${logsDir}'`,`exec 2>> '${crashLog}'`,`printf -- '--- tui-launch %s pid=%s ---\\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$$" >&2`,`export ${envVars.join(`
|
|
2503
2503
|
export `)}`,`exec ${bunPath} ${genieBin}`,""].join(`
|
|
2504
2504
|
`);writeFileSync16(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(`
|
|
2505
2505
|
`).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((resolve10)=>setTimeout(resolve10,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:join57}=__require("path"),configPath2=join57(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 startPgserve(){console.log(" Starting pgserve daemon...");try{let{getDataDir:getDataDir2,getOrStartDaemon:getOrStartDaemon2,resolvePgserveSocketDir:resolvePgserveSocketDir2}=await Promise.resolve().then(() => (init_db(),exports_db)),state=await getOrStartDaemon2(),pid=state.pid?`, pid ${state.pid}`:"";console.log(` pgserve daemon ready on ${resolvePgserveSocketDir2()} (data: ${getDataDir2()}${pid})`);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 failed: ${msg}`),process.env.GENIE_PG_NO_AUTOSTART="1",process.env.GENIE_PG_DISABLE_AUTOSTART="1",console.error(" pgserve retries disabled for this serve process; fix pgserve and restart `genie serve`.")}}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();mkdirSync18(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=join56(genieHome3(),"pgserve.port");if(existsSync45(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()}catch(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(`
|
|
2506
|
-
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(status){let statusPath=process.env.GENIE_SERVE_STARTUP_STATUS;if(!statusPath)return;try{mkdirSync18(
|
|
2506
|
+
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(status){let statusPath=process.env.GENIE_SERVE_STARTUP_STATUS;if(!statusPath)return;try{mkdirSync18(dirname15(statusPath),{recursive:!0}),writeFileSync16(statusPath,`${JSON.stringify(status)}
|
|
2507
2507
|
`,"utf-8")}catch{}}function readStartupStatus(statusPath){try{let parsed=JSON.parse(readFileSync27(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 status=readStartupStatus(statusPath);if(status)return status;if(!isProcessAlive(childPid))return{ok:!1,code:1};await new Promise((resolve10)=>setTimeout(resolve10,100))}return null}function exitBackgroundStartFailed(){console.error("Error: genie serve exited immediately."),process.exit(1)}function exitStartupStatusFailure(status){for(let line of status.lines??[])console.error(line);process.exit(status.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 status=await waitForStartupStatus(startupStatusPath,childPid,16000);if(forceRemovePath(startupStatusPath),status?.ok===!1)exitStartupStatusFailure(status);if(status?.ok!==!0)exitStartupStatusMissing(childPid);if(!isProcessAlive(childPid))exitBackgroundStartFailed();console.log(`genie serve started (PID ${childPid})`);return}if(await new Promise((resolve10)=>setTimeout(resolve10,1000)),!isProcessAlive(childPid))exitBackgroundStartFailed();console.log(`genie serve started (PID ${childPid})`)}async function startForeground(headless,autoFix=!0){claimServePidOrExit(),removeLegacyPgservePortLockfileIfForcedTcp();let{skipTui,mode}=resolveServeMode(headless);process.env.GENIE_IS_DAEMON="1",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 startPgserve(),await startBrainServerIfEnabled(),!headless)logAgentSessionInfo();handles.agentWatcher=await startAgentSync(),startTuiSessionIfEnabled(skipTui),await startScheduler(),await startDetectorSchedulerSafely(),await startExecutorReadEndpointSafely(),await startOmniApprovalHandlerSafely(),await startOmniBridgeSafely(),await startHookSocketSafely(),console.log(`
|
|
2508
2508
|
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){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((resolve10)=>setTimeout(resolve10,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??join56(genieHome3(),"hook.sock")}function warnIfHookSocketMissing(){let sock=hookSocketPath();if(existsSync45(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(`
|
|
2509
2509
|
`))}function printHookSocketStatus(){let sock=hookSocketPath();if(existsSync45(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(join56(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=join56(genieHome3(),"scheduler.pid");if(existsSync45(schedulerPidPath)){let sPid=Number.parseInt(readFileSync27(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(`
|
|
@@ -2818,7 +2818,7 @@ Genie Serve`),console.log("\u2500".repeat(50)),console.log(` Status: ${runn
|
|
|
2818
2818
|
SELECT * FROM assignments
|
|
2819
2819
|
WHERE executor_id = ${executorId}
|
|
2820
2820
|
ORDER BY started_at ASC
|
|
2821
|
-
`).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 existsSync54}from"fs";import{readFile as readFile12}from"fs/promises";import{dirname as
|
|
2821
|
+
`).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 existsSync54}from"fs";import{readFile as readFile12}from"fs/promises";import{dirname as dirname19,join as join65}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 existsSync54(logicalPath)?logicalPath:path3}function resolveWishPath(slug,cwd){let base=cwd??process.cwd(),cwdPath=join65(base,".genie","wishes",slug,"WISH.md");if(existsSync54(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(dirname19(commonDir));if(repoRoot!==base){let repoPath=join65(repoRoot,".genie","wishes",slug,"WISH.md");if(existsSync54(repoPath))return repoPath}}catch{}return findWishInWorkspaceRepos(slug)}function findWishInWorkspaceRepos(slug){try{let home=process.env.GENIE_HOME??join65(__require("os").homedir(),".genie"),configPath2=join65(home,"config.json");if(!existsSync54(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=join65(root,".genie","wishes",slug,"WISH.md");if(existsSync54(candidate))return candidate}}catch{}return null}function collectRepoCandidates(workspaceRoot){let fs2=__require("fs"),candidates=[workspaceRoot],reposDir=join65(workspaceRoot,"repos");try{if(fs2.existsSync(reposDir)){for(let entry2 of fs2.readdirSync(reposDir,{withFileTypes:!0}))if(entry2.isDirectory())candidates.push(join65(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())`
|
|
2822
2822
|
UPDATE agents
|
|
2823
2823
|
SET auto_resume = false,
|
|
2824
2824
|
state = 'archived',
|
|
@@ -2848,7 +2848,7 @@ ${broadcastLines}`}await handleWorkerSpawn2("team-lead",{provider:"claude",team:
|
|
|
2848
2848
|
ORDER BY m.created_at ASC
|
|
2849
2849
|
LIMIT 20
|
|
2850
2850
|
`).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 status=t.status??"in_progress",dimmed=status==="archived"?"\x1B[90m":"",reset2=status==="archived"?"\x1B[0m":"";console.log(` ${dimmed}${t.name} [${status}]${reset2}`),console.log(` Repo: ${t.repo}`),console.log(` Branch: ${t.name} (from ${t.baseBranch})`),console.log(` Worktree: ${t.worktreePath}`),console.log(` Members: ${t.members.length}`)}async function findTeamWindow(sessionName,teamName){let tmuxLib=await Promise.resolve().then(() => (init_tmux(),exports_tmux));if(!await tmuxLib.findSessionByName(sessionName))return null;try{return(await tmuxLib.listWindows(sessionName)).find((w)=>w.name===teamName||w.name===teamName.replace(/\./g,"_"))??null}catch{return null}}async function cleanupTeamWindow(t,dryRun){if(!t.tmuxSessionName)return null;let match=await findTeamWindow(t.tmuxSessionName,t.name);if(!match)return null;if(dryRun)return` [dry-run] Would kill window "${match.name}" in session "${t.tmuxSessionName}" (team "${t.name}" [${t.status}])`;if(!await(await Promise.resolve().then(() => (init_tmux(),exports_tmux))).killWindow(t.tmuxSessionName,match.name))return null;return` Killed window "${match.name}" in session "${t.tmuxSessionName}" (team "${t.name}")`}async function handleTeamCleanup(options){let cleanable=(await 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(`
|
|
2851
|
-
${verb} ${cleaned} window${cleaned===1?"":"s"}.`)}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 existsSync56,readFileSync as readFileSync35,readdirSync as readdirSync11}from"fs";import{basename as
|
|
2851
|
+
${verb} ${cleaned} window${cleaned===1?"":"s"}.`)}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 existsSync56,readFileSync as readFileSync35,readdirSync as readdirSync11}from"fs";import{basename as basename12,join as join67}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=join67(repoPath,".genie","wishes");if(!existsSync56(wishesDir))return[];let results=[],namespace=basename12(repoPath);try{let entries=readdirSync11(wishesDir,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;let wishPath=join67(wishesDir,entry2.name,"WISH.md");if(!existsSync56(wishPath))continue;try{let content=readFileSync35(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(!existsSync56(REPOS_BASE2))return[];let results=[];try{let entries=readdirSync11(REPOS_BASE2,{withFileTypes:!0});for(let entry2 of entries){if(!entry2.isDirectory())continue;results.push(...scanRepoWishes(join67(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`
|
|
2852
2852
|
INSERT INTO wishes (slug, repo, namespace, status, file_path)
|
|
2853
2853
|
VALUES (${wish.slug}, ${wish.repo}, ${wish.namespace}, ${wish.status}, ${wish.filePath})
|
|
2854
2854
|
ON CONFLICT (slug, repo) DO UPDATE SET
|
|
@@ -2995,7 +2995,7 @@ ${label} <TODO>
|
|
|
2995
2995
|
${actor},
|
|
2996
2996
|
${tx.json({agent_id:row.agent_id,outcome:TRAP_OUTCOME,reason})}
|
|
2997
2997
|
)
|
|
2998
|
-
`,{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 resolve18,dirname as dirname24}from"path";import{fileURLToPath as fileURLToPath4}from"url";import{resolve as resolve22,isAbsolute as isAbsolute4,parse as parse2}from"path";import{existsSync as existsSync68}from"fs";import{basename as basename13,join as join82}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{dlopen,toArrayBuffer as toArrayBuffer4,JSCallback,ptr as ptr4}from"bun:ffi";import{existsSync as existsSync210,writeFileSync as writeFileSync29}from"fs";import{EventEmitter as EventEmitter4}from"events";import{toArrayBuffer,ptr}from"bun:ffi";import{ptr as ptr2,toArrayBuffer as toArrayBuffer2}from"bun:ffi";import{ptr as ptr3,toArrayBuffer as toArrayBuffer3}from"bun:ffi";import{EventEmitter as EventEmitter5}from"events";import util3 from"util";import{EventEmitter as 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 normalizeColorTag(tag){let normalizedTag=tag!=null&&Number.isFinite(tag)?Math.round(tag):COLOR_TAG_RGB;if(normalizedTag===COLOR_TAG_RGB||normalizedTag===COLOR_TAG_DEFAULT)return normalizedTag;if(Number.isInteger(normalizedTag)&&normalizedTag>=0&&normalizedTag<=255)return normalizedTag;return COLOR_TAG_RGB}function normalizeRGBABuffer(buffer2){if(buffer2.length===RGBA_BUFFER_STRIDE)return buffer2[4]=normalizeColorTag(buffer2[4]),buffer2;let normalized=new Float32Array(RGBA_BUFFER_STRIDE);return normalized[0]=buffer2[0]??0,normalized[1]=buffer2[1]??0,normalized[2]=buffer2[2]??0,normalized[3]=buffer2[3]??0,normalized[4]=COLOR_TAG_RGB,normalized}function withTag(rgba,tag){let tagged=RGBA.clone(rgba);return tagged.tag=tag,tagged}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]}function decodeColorTag(tag){if(tag===COLOR_TAG_DEFAULT)return{kind:"default"};if(tag===COLOR_TAG_RGB)return{kind:"rgb"};return{kind:"indexed",index:normalizeIndexedColorIndex(tag)}}class RGBA{buffer;constructor(buffer2){this.buffer=normalizeRGBABuffer(buffer2)}static fromArray(array){return new RGBA(array)}static fromValues(r,g,b2,a=1,tag=COLOR_TAG_RGB){return new RGBA(new Float32Array([r,g,b2,a,normalizeColorTag(tag)]))}static clone(rgba){return RGBA.fromValues(rgba.r,rgba.g,rgba.b,rgba.a,rgba.tag)}static fromInts(r,g,b2,a=255,tag=COLOR_TAG_RGB){return new RGBA(new Float32Array([r/255,g/255,b2/255,a/255,normalizeColorTag(tag)]))}static fromHex(hex){return hexToRgb2(hex)}static fromIndex(index,snapshot){let normalizedIndex=normalizeIndexedColorIndex(index);return withTag(snapshot?parseColor(snapshot):rgbaForAnsi256Index(normalizedIndex),normalizedIndex)}static defaultForeground(snapshot){return withTag(snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_FOREGROUND_RGB),COLOR_TAG_DEFAULT)}static defaultBackground(snapshot){return withTag(snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_BACKGROUND_RGB),COLOR_TAG_DEFAULT)}static getIntentTag(rgba){return rgba.tag}toInts(){return[Math.round(this.r*255),Math.round(this.g*255),Math.round(this.b*255),Math.round(this.a*255)]}get r(){return this.buffer[0]}set r(value){this.buffer[0]=value}get g(){return this.buffer[1]}set g(value){this.buffer[1]=value}get b(){return this.buffer[2]}set b(value){this.buffer[2]=value}get a(){return this.buffer[3]}set a(value){this.buffer[3]=value}get tag(){return normalizeColorTag(this.buffer[4])}set tag(value){this.buffer[4]=normalizeColorTag(value)}map(fn){return[fn(this.r),fn(this.g),fn(this.b),fn(this.a)]}toString(){return`rgba(${this.r.toFixed(2)}, ${this.g.toFixed(2)}, ${this.b.toFixed(2)}, ${this.a.toFixed(2)})`}equals(other){if(!other)return!1;return this.r===other.r&&this.g===other.g&&this.b===other.b&&this.a===other.a&&this.tag===other.tag}}function normalizeColorValue(value){if(value==null)return null;let rgba=parseColor(value);return{rgba,tag:rgba.tag}}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)/255,g=parseInt(hex.substring(2,4),16)/255,b2=parseInt(hex.substring(4,6),16)/255,a=hex.length===8?parseInt(hex.substring(6,8),16)/255:1;return RGBA.fromValues(r,g,b2,a)}function rgbToHex2(rgb){return"#"+(rgb.a===1?[rgb.r,rgb.g,rgb.b]:[rgb.r,rgb.g,rgb.b,rgb.a]).map((x)=>{let hex=Math.floor(Math.max(0,Math.min(1,x)*255)).toString(16);return hex.length===1?"0"+hex:hex}).join("")}function hsvToRgb(h,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:
|
|
2998
|
+
`,{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 resolve18,dirname as dirname25}from"path";import{fileURLToPath as fileURLToPath4}from"url";import{resolve as resolve22,isAbsolute as isAbsolute4,parse as parse2}from"path";import{existsSync as existsSync68}from"fs";import{basename as basename14,join as join82}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{dlopen,toArrayBuffer as toArrayBuffer4,JSCallback,ptr as ptr4}from"bun:ffi";import{existsSync as existsSync210,writeFileSync as writeFileSync29}from"fs";import{EventEmitter as EventEmitter4}from"events";import{toArrayBuffer,ptr}from"bun:ffi";import{ptr as ptr2,toArrayBuffer as toArrayBuffer2}from"bun:ffi";import{ptr as ptr3,toArrayBuffer as toArrayBuffer3}from"bun:ffi";import{EventEmitter as EventEmitter5}from"events";import util3 from"util";import{EventEmitter as 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 normalizeColorTag(tag){let normalizedTag=tag!=null&&Number.isFinite(tag)?Math.round(tag):COLOR_TAG_RGB;if(normalizedTag===COLOR_TAG_RGB||normalizedTag===COLOR_TAG_DEFAULT)return normalizedTag;if(Number.isInteger(normalizedTag)&&normalizedTag>=0&&normalizedTag<=255)return normalizedTag;return COLOR_TAG_RGB}function normalizeRGBABuffer(buffer2){if(buffer2.length===RGBA_BUFFER_STRIDE)return buffer2[4]=normalizeColorTag(buffer2[4]),buffer2;let normalized=new Float32Array(RGBA_BUFFER_STRIDE);return normalized[0]=buffer2[0]??0,normalized[1]=buffer2[1]??0,normalized[2]=buffer2[2]??0,normalized[3]=buffer2[3]??0,normalized[4]=COLOR_TAG_RGB,normalized}function withTag(rgba,tag){let tagged=RGBA.clone(rgba);return tagged.tag=tag,tagged}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]}function decodeColorTag(tag){if(tag===COLOR_TAG_DEFAULT)return{kind:"default"};if(tag===COLOR_TAG_RGB)return{kind:"rgb"};return{kind:"indexed",index:normalizeIndexedColorIndex(tag)}}class RGBA{buffer;constructor(buffer2){this.buffer=normalizeRGBABuffer(buffer2)}static fromArray(array){return new RGBA(array)}static fromValues(r,g,b2,a=1,tag=COLOR_TAG_RGB){return new RGBA(new Float32Array([r,g,b2,a,normalizeColorTag(tag)]))}static clone(rgba){return RGBA.fromValues(rgba.r,rgba.g,rgba.b,rgba.a,rgba.tag)}static fromInts(r,g,b2,a=255,tag=COLOR_TAG_RGB){return new RGBA(new Float32Array([r/255,g/255,b2/255,a/255,normalizeColorTag(tag)]))}static fromHex(hex){return hexToRgb2(hex)}static fromIndex(index,snapshot){let normalizedIndex=normalizeIndexedColorIndex(index);return withTag(snapshot?parseColor(snapshot):rgbaForAnsi256Index(normalizedIndex),normalizedIndex)}static defaultForeground(snapshot){return withTag(snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_FOREGROUND_RGB),COLOR_TAG_DEFAULT)}static defaultBackground(snapshot){return withTag(snapshot?parseColor(snapshot):RGBA.fromInts(...DEFAULT_BACKGROUND_RGB),COLOR_TAG_DEFAULT)}static getIntentTag(rgba){return rgba.tag}toInts(){return[Math.round(this.r*255),Math.round(this.g*255),Math.round(this.b*255),Math.round(this.a*255)]}get r(){return this.buffer[0]}set r(value){this.buffer[0]=value}get g(){return this.buffer[1]}set g(value){this.buffer[1]=value}get b(){return this.buffer[2]}set b(value){this.buffer[2]=value}get a(){return this.buffer[3]}set a(value){this.buffer[3]=value}get tag(){return normalizeColorTag(this.buffer[4])}set tag(value){this.buffer[4]=normalizeColorTag(value)}map(fn){return[fn(this.r),fn(this.g),fn(this.b),fn(this.a)]}toString(){return`rgba(${this.r.toFixed(2)}, ${this.g.toFixed(2)}, ${this.b.toFixed(2)}, ${this.a.toFixed(2)})`}equals(other){if(!other)return!1;return this.r===other.r&&this.g===other.g&&this.b===other.b&&this.a===other.a&&this.tag===other.tag}}function normalizeColorValue(value){if(value==null)return null;let rgba=parseColor(value);return{rgba,tag:rgba.tag}}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)/255,g=parseInt(hex.substring(2,4),16)/255,b2=parseInt(hex.substring(4,6),16)/255,a=hex.length===8?parseInt(hex.substring(6,8),16)/255:1;return RGBA.fromValues(r,g,b2,a)}function rgbToHex2(rgb){return"#"+(rgb.a===1?[rgb.r,rgb.g,rgb.b]:[rgb.r,rgb.g,rgb.b,rgb.a]).map((x)=>{let hex=Math.floor(Math.max(0,Math.min(1,x)*255)).toString(16);return hex.length===1?"0"+hex:hex}).join("")}function hsvToRgb(h,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:
|
|
2999
2999
|
`+treeLines.join(`
|
|
3000
3000
|
`))}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(`
|
|
3001
3001
|
`)}}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
|
|
@@ -3023,7 +3023,7 @@ No environment variables registered.
|
|
|
3023
3023
|
`}else output+=`\x1B[32mDefault:\x1B[0m \x1B[31mRequired\x1B[0m
|
|
3024
3024
|
`;output+=`
|
|
3025
3025
|
`}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 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_MS),this.maxPendingBytes=normalizePositiveOption(options.maxPendingBytes,DEFAULT_MAX_PENDING_BYTES),this.armTimeouts=options.armTimeouts??!0,this.onTimeoutFlush=options.onTimeoutFlush??null,this.useKittyKeyboard=options.useKittyKeyboard??!0,this.clock=options.clock??SYSTEM_CLOCK,this.protocolContext={...DEFAULT_PROTOCOL_CONTEXT,kittyKeyboardEnabled:options.protocolContext?.kittyKeyboardEnabled??!1,privateCapabilityRepliesActive:options.protocolContext?.privateCapabilityRepliesActive??!1,pixelResolutionQueryActive:options.protocolContext?.pixelResolutionQueryActive??!1,explicitWidthCprActive:options.protocolContext?.explicitWidthCprActive??!1,startupCursorCprActive:options.protocolContext?.startupCursorCprActive??!1}}get bufferCapacity(){return this.pending.capacity}updateProtocolContext(patch){this.ensureAlive(),this.protocolContext={...this.protocolContext,...patch},this.reconcileDeferredStateWithProtocolContext(),this.reconcileTimeoutState()}push(data){if(this.ensureAlive(),data.length===0){this.emitKeyOrResponse("unknown","");return}let remainder=data;while(remainder.length>0){if(this.paste){remainder=this.consumePasteBytes(remainder);continue}let immediatePasteStartIndex=this.state.tag==="ground"&&this.pending.length===0?indexOfBytes(remainder,BRACKETED_PASTE_START):-1,appendEnd=immediatePasteStartIndex===-1?remainder.length:immediatePasteStartIndex+BRACKETED_PASTE_START.length;if(this.pending.append(remainder.subarray(0,appendEnd)),remainder=remainder.subarray(appendEnd),this.scanPending(),this.paste&&this.pending.length>0){remainder=this.consumePasteBytes(this.takePendingBytes());continue}if(!this.paste&&this.pending.length>this.maxPendingBytes){if(this.flushPendingOverflow(),this.scanPending(),this.paste&&this.pending.length>0)remainder=this.consumePasteBytes(this.takePendingBytes())}}this.reconcileTimeoutState()}read(){if(this.ensureAlive(),this.events.length===0&&this.forceFlush)this.scanPending(),this.reconcileTimeoutState();return this.events.shift()??null}drain(onEvent){this.ensureAlive();while(!0){if(this.destroyed)return;let event=this.read();if(!event)return;onEvent(event)}}flushTimeout(nowMsValue=this.clock.now()){if(this.ensureAlive(),this.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_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&¤tOffset<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]===`
|
|
3026
|
-
`){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((resolve20,reject)=>{if(scopeMap.has(id))clearTimeout(scopeMap.get(id));let timerId=setTimeout(()=>{try{resolve20(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:[resolve18(
|
|
3026
|
+
`){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((resolve20,reject)=>{if(scopeMap.has(id))clearTimeout(scopeMap.get(id));let timerId=setTimeout(()=>{try{resolve20(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:[resolve18(dirname25(fileURLToPath4(import.meta.url)),highlights_default)]},wasm:resolve18(dirname25(fileURLToPath4(import.meta.url)),tree_sitter_javascript_default)},{filetype:"typescript",aliases:["typescriptreact"],queries:{highlights:[resolve18(dirname25(fileURLToPath4(import.meta.url)),highlights_default2)]},wasm:resolve18(dirname25(fileURLToPath4(import.meta.url)),tree_sitter_typescript_default)},{filetype:"markdown",queries:{highlights:[resolve18(dirname25(fileURLToPath4(import.meta.url)),highlights_default3)],injections:[resolve18(dirname25(fileURLToPath4(import.meta.url)),injections_default)]},wasm:resolve18(dirname25(fileURLToPath4(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:[resolve18(dirname25(fileURLToPath4(import.meta.url)),highlights_default4)]},wasm:resolve18(dirname25(fileURLToPath4(import.meta.url)),tree_sitter_markdown_inline_default)},{filetype:"zig",queries:{highlights:[resolve18(dirname25(fileURLToPath4(import.meta.url)),highlights_default5)]},wasm:resolve18(dirname25(fileURLToPath4(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 join82(getBunfsRootPath(),basename14(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(`
|
|
3027
3027
|
`)}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(__dirname2,"../parsers-config"),assetsDir:path4.resolve(__dirname2),outputPath:path4.resolve(__dirname2,"../default-parsers.ts")}}async function loadConfig2(configPath2){let ext=path4.extname(configPath2),resolvedConfigPath=configPath2;if(ext===""){let file=(await 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(`
|
|
3028
3028
|
`).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}
|
|
3029
3029
|
${content}`),console.log(` \u2713 Downloaded ${content.split(`
|
|
@@ -3856,7 +3856,7 @@ Bus `);for(let i2=1;i2<parts.length;i2++){let usb2=parseLinuxUsb(parts[i2]);resu
|
|
|
3856
3856
|
`),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);resolve20(result2)});if(_freebsd||_netbsd||_openbsd||_sunos)resolve20(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((resolve20)=>{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);resolve20(data)})})})}function getDynamicData(srv,iface,callback){if(util4.isFunction(iface))callback=iface,iface="";if(util4.isFunction(srv))callback=srv,srv="";return new Promise((resolve20)=>{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);resolve20(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((resolve20)=>{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);resolve20(data)})})})})}function get3(valueObject,callback){return new Promise((resolve20)=>{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);resolve20(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_react19.useState(null),mountedRef=import_react19.useRef(!0);return import_react19.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_react19,import_systeminformation;var init_SystemStats=__esm(()=>{init_version();init_theme2();init_jsx_dev_runtime();import_react19=__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_react21.useState("name"),[teamName,setTeamName]=import_react21.useState(""),[selected,setSelected]=import_react21.useState(()=>new Set),[memberCursor,setMemberCursor]=import_react21.useState(0),nameError=import_react21.useMemo(()=>validateName(teamName),[teamName]),nameValid=teamName.length>0&&nameError===null,intent=import_react21.useMemo(()=>({kind:"create-team",name:teamName.length>0?teamName:"TEAM_NAME",repo:workspaceRoot}),[teamName,workspaceRoot]),handleNameChange=import_react21.useCallback((value)=>{setTeamName(value)},[]),advanceFromName=import_react21.useCallback(()=>{if(!nameValid)return;setStep("members")},[nameValid]),toggleMember=import_react21.useCallback((name)=>{setSelected((prev)=>{let next=new Set(prev);if(next.has(name))next.delete(name);else next.add(name);return next})},[]),confirmMembers=import_react21.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_react21;var init_TeamCreate=__esm(async()=>{init_team_manager();init_theme2();init_CliPreviewLine();init_jsx_dev_runtime();await init_react();import_react21=__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_react22,TreeNodeRow;var init_TreeNode=__esm(()=>{init_theme2();init_jsx_dev_runtime();import_react22=__toESM(require_react_development(),1),TreeNodeRow=import_react22.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),suffix=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),suffix?import_jsx_dev_runtime2.jsxDEV("span",{fg:palette.textDim,children:suffix},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_react24.useEffect(()=>{let active=!0;async function refresh(){try{let snap=await collectDiagnostics();if(!active)return;setDiagnostics(snap);let signaledAgent=consumeInitialAgentSignal();if(signaledAgent)setRequestedInitialAgent(signaledAgent)}catch(err){console.error("TUI: diagnostics failed:",err)}}refresh();let timer2=setInterval(refresh,2000);return()=>{active=!1,clearInterval(timer2)}},[setDiagnostics,setRequestedInitialAgent])}function useSessionTreeBuilder(diagnostics,workspaceRoot,setSessionTree){import_react24.useEffect(()=>{if(!diagnostics)return;let newTree;if(workspaceRoot){let agentNames=scanAgents(workspaceRoot);newTree=buildWorkspaceTree({agentNames,sessions:diagnostics.sessions,executors:diagnostics.executors,workStates:diagnostics.workStates})}else newTree=buildSessionTree(diagnostics);setSessionTree((prev)=>mergeExpandedState(prev,newTree))},[diagnostics,workspaceRoot,setSessionTree])}function useStableSelection(flatNodes,selectedIndex,setSelectedIndex,selectedNodeId){import_react24.useEffect(()=>{let node=flatNodes[selectedIndex]?.node;if(node)selectedNodeId.current=node.id},[selectedIndex,flatNodes,selectedNodeId]),import_react24.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&¤tAtIndex.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_react24.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_react24.useEffect(()=>{let current=flatNodes[selectedIndex]?.node;if(!current)return;let target=getSessionTarget(current);if(!target)return;if(current.type==="agent"&¤t.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_react24.useState(null),[sessionTree,setSessionTree]=import_react24.useState([]),[selectedIndex,setSelectedIndex]=import_react24.useState(0),[requestedInitialAgent,setRequestedInitialAgent]=import_react24.useState(initialAgent),[contextMenuNodeId,setContextMenuNodeId]=import_react24.useState(null),[spawnIntoAgent,setSpawnIntoAgent]=import_react24.useState(null),[spawnPickerTarget,setSpawnPickerTarget]=import_react24.useState(null),lastTarget=import_react24.useRef(null),selectedNodeId=import_react24.useRef(null);useDiagnosticsRefresh(setDiagnostics,setRequestedInitialAgent),useSessionTreeBuilder(diagnostics,workspaceRoot,setSessionTree);let flatNodes=import_react24.useMemo(()=>flattenTree(sessionTree),[sessionTree]);useStableSelection(flatNodes,selectedIndex,setSelectedIndex,selectedNodeId),useInitialAgentSelection(requestedInitialAgent,flatNodes,setSelectedIndex,setRequestedInitialAgent,onTmuxSessionSelect),useAutoAttach(flatNodes,selectedIndex,lastTarget,onTmuxSessionSelect);let handleSelect=import_react24.useCallback((id)=>{let idx=flatNodes.findIndex((n)=>n.node.id===id);if(idx>=0)setSelectedIndex(idx)},[flatNodes]),handleToggle=import_react24.useCallback((id)=>{setSessionTree((prev)=>toggleNode(prev,id))},[]),handleVerticalNav=import_react24.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_react24.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_react24.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_react24.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_react24.useCallback((nodeId)=>{let flat=flatNodes.find((n)=>n.node.id===nodeId);if(flat&&buildMenuItems(flat.node).length>0)setContextMenuNodeId(nodeId)},[flatNodes]),handleContextMenuAction=import_react24.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_react24.useCallback((intent)=>{executeSpawnIntent(intent),setSpawnIntoAgent(null)},[]),handleSpawnIntoCancel=import_react24.useCallback(()=>{setSpawnIntoAgent(null)},[]),handleSpawnPickerConfirm=import_react24.useCallback((intent)=>{setSpawnPickerTarget(null),executeSpawnIntent(intent)},[]),handleSpawnPickerCancel=import_react24.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",children:import_jsx_dev_runtime2.jsxDEV("text",{fg:palette.textDim,children:"Collecting..."},void 0,!1,void 0,this)},void 0,!1,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?scanAgents(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_react24.useState(!1),pendingTeamNameRef=import_react24.useRef(null),handleOpenTeamCreate=import_react24.useCallback(()=>{if(!workspaceRoot)return;setShowTeamCreate(!0)},[workspaceRoot]),handleTeamCreateConfirm=import_react24.useCallback((result2)=>{setShowTeamCreate(!1),runTeamCreation(result2,workspaceRoot),pendingTeamNameRef.current=result2.teamName},[workspaceRoot]),handleTeamCreateCancel=import_react24.useCallback(()=>{setShowTeamCreate(!1)},[]);return import_react24.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),suffix=Date.now()%1e4,role=`${agentFullName}-${suffix}`;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:join86,resolve:resolve20}=__require("path"),{existsSync:existsSync70,mkdirSync:mkdirSync29,openSync:openSync6}=__require("fs"),{homedir:homedir45}=__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=resolve20(join86(wsRoot,"agents",parentName));if(existsSync70(agentDir))cwd=agentDir}let{GENIE_TUI_PANE:_a,GENIE_TUI_RIGHT:_b,GENIE_TUI_WORKSPACE:_c,GENIE_IS_DAEMON:_d,...cleanEnv}=process.env,logDir=join86(homedir45(),".genie","logs","tui-spawn");try{mkdirSync29(logDir,{recursive:!0})}catch{}let logPath=join86(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((resolve20,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)=>resolve20(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_react24;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_react(),init_AgentPicker(),init_ContextMenu(),init_SpawnTargetPicker(),init_TeamCreate()]);import_react24=__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:"Quit genie?"},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 quit "},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:"Hint: Ctrl+D to detach (keep running)"},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_react()});import{execSync as execSync18}from"child_process";import{readFileSync as readFileSync44}from"fs";function App({rightPane,workspaceRoot,initialAgent}){let[showQuit,setShowQuit]=import_react27.useState(!1);useKeyboard((key)=>{if(key.ctrl&&key.name==="q")if(showQuit)handleQuit();else setShowQuit(!0)});let handleQuit=import_react27.useCallback(()=>{try{let genieHome6=process.env.GENIE_HOME??`${process.env.HOME}/.genie`,pid=readFileSync44(`${genieHome6}/serve.pid`,"utf-8").trim();process.kill(Number.parseInt(pid,10),"SIGTERM")}catch{}try{execSync18("tmux -L genie-tui kill-server",{stdio:"ignore"})}catch{}},[]),handleTmuxSessionSelect=import_react27.useCallback((sessionName,windowIndex)=>{if(!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},void 0,!1,void 0,this),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_react27;var init_app=__esm(async()=>{init_tmux2();init_jsx_dev_runtime();await __promiseAll([init_react(),init_Nav(),init_QuitDialog()]);import_react27=__toESM(require_react_development(),1)});var exports_render={};__export(exports_render,{resolveTuiRendererConfig:()=>resolveTuiRendererConfig,renderNav:()=>renderNav});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){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=readPositiveInt(env2,"GENIE_TUI_TARGET_FPS")??(isDarwin?8:30),configuredMaxFps=readPositiveInt(env2,"GENIE_TUI_MAX_FPS")??(isDarwin?12:60),maxFps=Math.max(configuredMaxFps,targetFps),useMouse=readBool(env2,"GENIE_TUI_MOUSE",!isDarwin),enableMouseMovement=useMouse&&readBool(env2,"GENIE_TUI_MOUSE_MOVEMENT",!isDarwin);return{exitOnCtrlC:!1,useThread:!isDarwin,targetFps,maxFps,useMouse,enableMouseMovement,useKittyKeyboard:isDarwin?null:void 0,consoleMode:isDarwin?"disabled":void 0,openConsoleOnError:!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());createRoot(renderer).render(import_jsx_dev_runtime2.jsxDEV(App,{rightPane,workspaceRoot,initialAgent},void 0,!1,void 0,this)),await new Promise((resolve20)=>{renderer.once("destroy",resolve20)})}var TRUTHY3,FALSY;var init_render=__esm(async()=>{init_jsx_dev_runtime();await __promiseAll([init_core(),init_react(),init_app()]);TRUTHY3=new Set(["1","true","yes","on"]),FALSY=new Set(["0","false","no","off"])});var exports_tui={};__export(exports_tui,{launchTui:()=>launchTui});import{appendFileSync as appendFileSync4,closeSync as closeSync6,mkdirSync as mkdirSync29,openSync as openSync6,readSync as readSync3,statSync as statSync13}from"fs";import{homedir as homedir45}from"os";import{join as join86}from"path";function genieHome6(){return process.env.GENIE_HOME??join86(homedir45(),".genie")}function extractPreviousRunCrashOutput(logPath){let fd=null;try{let size=statSync13(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(`
|
|
3857
3857
|
`,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)}
|
|
3858
3858
|
\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=join86(genieHome6(),"logs");mkdirSync29(logsDir,{recursive:!0});let logPath=join86(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} ---
|
|
3859
|
-
`;appendFileSync4(logPath,line,{mode:420})}catch{}}async function launchTui(){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 existsSync70}from"fs";import{basename as basename16,dirname as dirname27,join as join87,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(!existsSync70(join87(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&¤t!==dirname27(current)){if(existsSync70(join87(current,"AGENTS.md")))return{agent:basename16(current),source:"parent"};current=dirname27(current)}return null}function resolveAgentFromCwd(cwd,workspaceRoot){return resolveFromCanonicalDir(cwd,join87(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();init_setup();init_shortcuts();import{existsSync as existsSync23}from"fs";import{homedir as homedir24}from"os";import{join as join29}from"path";async function shortcutsShowCommand(){displayShortcuts();let home=homedir24(),tmuxConf=join29(home,".tmux.conf"),zshrc=join29(home,".zshrc"),bashrc=join29(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=existsSync23(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 existsSync24,lstatSync,rmSync as rmSync2,unlinkSync as unlinkSync8}from"fs";import{homedir as homedir25}from"os";import{join as join30}from"path";var ORCHESTRATION_RULES_PATH=join30(homedir25(),".claude","rules","genie-orchestration.md"),LOCAL_BIN=join30(homedir25(),".local","bin"),SYMLINKS=["genie","term"];function isGenieSymlink(path3){try{if(!existsSync24(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=join30(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(existsSync24(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=existsSync24(genieDir),hasHookScript=hookScriptExists(),hasOrchestrationRules=existsSync24(ORCHESTRATION_RULES_PATH),existingSymlinks=SYMLINKS.filter((name)=>isGenieSymlink(join30(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();import{execSync as execSync4,spawn as spawn3}from"child_process";import{chmodSync as chmodSync2,closeSync as closeSync3,copyFileSync as copyFileSync3,existsSync as existsSync25,mkdirSync as mkdirSync13,openSync as openSync3,readFileSync as readFileSync17,readSync as readSync2,readdirSync as readdirSync8,rmSync as rmSync3,statSync as statSync7,writeFileSync as writeFileSync11}from"fs";import{chmod,copyFile,mkdir as mkdir5,unlink as unlink2}from"fs/promises";import{homedir as homedir26}from"os";import{join as join31}from"path";var GENIE_HOME2=process.env.GENIE_HOME||join31(homedir26(),".genie"),GENIE_SRC=join31(GENIE_HOME2,"src"),GENIE_BIN=join31(GENIE_HOME2,"bin"),LOCAL_BIN2=join31(homedir26(),".local","bin"),TRUTHY=new Set(["1","true","yes","on"]),UPDATE_DIAGNOSTIC_SCHEMA_VERSION=1;function log(message){console.log(`\x1B[32m\u25B8\x1B[0m ${message}`)}function success(message){console.log(`\x1B[32m\u2714\x1B[0m ${message}`)}function error(message){console.log(`\x1B[31m\u2716\x1B[0m ${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 execSync4(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=readFileSync17(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=statSync7(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){let logsDir=join31(GENIE_HOME2,"logs");mkdirSync13(logsDir,{recursive:!0});let generatedAt=new Date().toISOString(),safeStamp=generatedAt.replace(/[:.]/g,"-"),path3=join31(logsDir,`update-diagnostics-${safeStamp}.json`),schedulerLog=join31(logsDir,"scheduler.log"),tuiCrashLog=join31(logsDir,"tui-crash.log"),signals2=summarizeJsonlSignals(schedulerLog),diagnostics={schemaVersion:UPDATE_DIAGNOSTIC_SCHEMA_VERSION,generatedAt,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(join31(GENIE_HOME2,"serve.pid"),200),pgservePort:safeRead(join31(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 writeFileSync11(path3,`${JSON.stringify(diagnostics,null,2)}
|
|
3859
|
+
`;appendFileSync4(logPath,line,{mode:420})}catch{}}async function launchTui(){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 existsSync70}from"fs";import{basename as basename17,dirname as dirname28,join as join87,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(!existsSync70(join87(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&¤t!==dirname28(current)){if(existsSync70(join87(current,"AGENTS.md")))return{agent:basename17(current),source:"parent"};current=dirname28(current)}return null}function resolveAgentFromCwd(cwd,workspaceRoot){return resolveFromCanonicalDir(cwd,join87(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();init_setup();init_shortcuts();import{existsSync as existsSync23}from"fs";import{homedir as homedir24}from"os";import{join as join29}from"path";async function shortcutsShowCommand(){displayShortcuts();let home=homedir24(),tmuxConf=join29(home,".tmux.conf"),zshrc=join29(home,".zshrc"),bashrc=join29(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=existsSync23(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 existsSync24,lstatSync,rmSync as rmSync2,unlinkSync as unlinkSync8}from"fs";import{homedir as homedir25}from"os";import{join as join30}from"path";var ORCHESTRATION_RULES_PATH=join30(homedir25(),".claude","rules","genie-orchestration.md"),LOCAL_BIN=join30(homedir25(),".local","bin"),SYMLINKS=["genie","term"];function isGenieSymlink(path3){try{if(!existsSync24(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=join30(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(existsSync24(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=existsSync24(genieDir),hasHookScript=hookScriptExists(),hasOrchestrationRules=existsSync24(ORCHESTRATION_RULES_PATH),existingSymlinks=SYMLINKS.filter((name)=>isGenieSymlink(join30(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();import{execSync as execSync4,spawn as spawn3}from"child_process";import{chmodSync as chmodSync2,closeSync as closeSync3,copyFileSync as copyFileSync3,existsSync as existsSync25,mkdirSync as mkdirSync13,openSync as openSync3,readFileSync as readFileSync17,readSync as readSync2,readdirSync as readdirSync8,rmSync as rmSync3,statSync as statSync7,writeFileSync as writeFileSync11}from"fs";import{chmod,copyFile,mkdir as mkdir5,unlink as unlink2}from"fs/promises";import{homedir as homedir26}from"os";import{join as join31}from"path";var GENIE_HOME2=process.env.GENIE_HOME||join31(homedir26(),".genie"),GENIE_SRC=join31(GENIE_HOME2,"src"),GENIE_BIN=join31(GENIE_HOME2,"bin"),LOCAL_BIN2=join31(homedir26(),".local","bin"),TRUTHY=new Set(["1","true","yes","on"]),UPDATE_DIAGNOSTIC_SCHEMA_VERSION=1;function log(message){console.log(`\x1B[32m\u25B8\x1B[0m ${message}`)}function success(message){console.log(`\x1B[32m\u2714\x1B[0m ${message}`)}function error(message){console.log(`\x1B[31m\u2716\x1B[0m ${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 execSync4(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=readFileSync17(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=statSync7(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){let logsDir=join31(GENIE_HOME2,"logs");mkdirSync13(logsDir,{recursive:!0});let generatedAt=new Date().toISOString(),safeStamp=generatedAt.replace(/[:.]/g,"-"),path3=join31(logsDir,`update-diagnostics-${safeStamp}.json`),schedulerLog=join31(logsDir,"scheduler.log"),tuiCrashLog=join31(logsDir,"tui-crash.log"),signals2=summarizeJsonlSignals(schedulerLog),diagnostics={schemaVersion:UPDATE_DIAGNOSTIC_SCHEMA_VERSION,generatedAt,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(join31(GENIE_HOME2,"serve.pid"),200),pgservePort:safeRead(join31(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 writeFileSync11(path3,`${JSON.stringify(diagnostics,null,2)}
|
|
3860
3860
|
`),{path:path3,signals:signals2}}async function runCommand(command,args,cwd){return new Promise((resolve4)=>{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)=>{resolve4({success:code===0,output:output.join("")})}),child.on("error",(err)=>{error(err.message),resolve4({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((resolve4)=>{let output=[],settled=!1,child=spawn3(command,args,{cwd,stdio:["inherit","pipe","pipe"]}),timer2=setTimeout(()=>{if(settled)return;settled=!0,child.kill("SIGTERM"),resolve4({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),resolve4({success:code===0,output:output.join("")})}),child.on("error",(err)=>{if(settled)return;settled=!0,clearTimeout(timer2),resolve4({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===join31(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(existsSync25(join31(GENIE_SRC,".git")))return"source";return(await runCommandSilent("which",["bun"])).success?"bun":"npm"}async function updateViaBun(channel){try{__require("fs").unlinkSync(join31(homedir26(),".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(!existsSync25(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(!existsSync25(join31(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=join31(GENIE_SRC,"dist",binaries[i2]),binDest=join31(GENIE_BIN,binaries[i2]),linkDest=join31(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=join31(GENIE_BIN,legacy),legacyLink=join31(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(existsSync25(dest))await unlink3(dest);await symlink2(src,dest)}catch{await copyFile(src,dest)}}function copyDirSync(src,dest){mkdirSync13(dest,{recursive:!0});for(let entry2 of readdirSync8(src,{withFileTypes:!0})){let srcPath=join31(src,entry2.name),destPath=join31(dest,entry2.name);if(entry2.isDirectory())copyDirSync(srcPath,destPath);else copyFileSync3(srcPath,destPath)}}async function resolveGlobalPkgDir(installType){if(installType==="bun"){let bunPath=join31(homedir26(),".bun","install","global","node_modules","@automagik","genie");if(existsSync25(bunPath))return bunPath}if(installType==="npm"){let npmRootResult=await runCommandSilent("npm",["root","-g"]);if(npmRootResult.success){let npmPath=join31(npmRootResult.output.trim(),"@automagik","genie");if(existsSync25(npmPath))return npmPath}}let bunFallback=join31(homedir26(),".bun","install","global","node_modules","@automagik","genie");if(existsSync25(bunFallback))return bunFallback;let npmRootFallback=await runCommandSilent("npm",["root","-g"]);if(npmRootFallback.success){let npmPath=join31(npmRootFallback.output.trim(),"@automagik","genie");if(existsSync25(npmPath))return npmPath}return null}function updatePluginRegistry(claudePlugins,cacheDir,version){let registryPath=join31(claudePlugins,"installed_plugins.json");try{if(!existsSync25(registryPath))return;let registry=JSON.parse(readFileSync17(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();writeFileSync11(registryPath,JSON.stringify(registry,null,2))}catch(err){log(`Registry update failed (non-fatal): ${err}`)}}function syncTmuxConf(tmuxScriptsSrc){mkdirSync13(GENIE_HOME2,{recursive:!0});let tmuxConfSrc=join31(tmuxScriptsSrc,"genie.tmux.conf"),tmuxConfDest=join31(GENIE_HOME2,"tmux.conf");if(existsSync25(tmuxConfSrc))try{copyFileSync3(tmuxConfSrc,tmuxConfDest),success(`Installed tmux config to ${tmuxConfDest}`);try{let{tmuxBin:tmuxBin2}=(init_ensure_tmux(),__toCommonJS(exports_ensure_tmux));execSync4(`${tmuxBin2()} -L genie source-file '${tmuxConfDest}'`,{stdio:"ignore"}),success("Reloaded genie tmux server configuration")}catch{}}catch{}let tuiConfSrc=join31(tmuxScriptsSrc,"tui-tmux.conf"),tuiConfDest=join31(GENIE_HOME2,"tui-tmux.conf");if(existsSync25(tuiConfSrc))try{copyFileSync3(tuiConfSrc,tuiConfDest),success(`Installed TUI tmux config to ${tuiConfDest}`)}catch{}let themeSrc=join31(tmuxScriptsSrc,".generated.theme.conf"),themeDest=join31(GENIE_HOME2,".generated.theme.conf");if(existsSync25(themeSrc))try{copyFileSync3(themeSrc,themeDest),success(`Installed tmux theme to ${themeDest}`)}catch{}let osc52Src=join31(tmuxScriptsSrc,"osc52-copy.sh"),osc52Dest=join31(GENIE_HOME2,"scripts","osc52-copy.sh");if(existsSync25(osc52Src))try{copyFileSync3(osc52Src,osc52Dest),chmodSync2(osc52Dest,493),success(`Installed OSC 52 clipboard helper to ${osc52Dest}`)}catch{}}function syncTmuxScripts(globalPkgDir){let tmuxScriptsSrc=join31(globalPkgDir,"scripts","tmux");if(!existsSync25(tmuxScriptsSrc))return;let scriptsDir=join31(GENIE_HOME2,"scripts");mkdirSync13(scriptsDir,{recursive:!0});let scriptCount=0;for(let entry2 of readdirSync8(tmuxScriptsSrc))if(entry2.endsWith(".sh")||entry2==="genie.tmux.conf"||entry2==="tui-tmux.conf"||entry2===".generated.theme.conf"){let src=join31(tmuxScriptsSrc,entry2),dest=join31(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=join31(claudePlugins,"marketplaces","automagik",".claude-plugin","marketplace.json");try{if(!existsSync25(marketplacePath))return;let data=JSON.parse(readFileSync17(marketplacePath,"utf-8"));if(Array.isArray(data.plugins)){for(let plugin of data.plugins)if(plugin.name==="genie")plugin.version=version}writeFileSync11(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=join31(claudePlugins,"marketplaces","automagik","plugins","genie","package.json");try{if(!existsSync25(pkgPath))return;let data=JSON.parse(readFileSync17(pkgPath,"utf-8"));data.version=version,writeFileSync11(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=join31(claudePlugins,"marketplaces","automagik","plugins","genie","skills"),cacheSkills=join31("..","..","..","..","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=join31(globalPkgDir,"plugins","genie");if(!existsSync25(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(readFileSync17(join31(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=join31(homedir26(),".claude","plugins"),cacheDir=join31(claudePlugins,"cache","automagik","genie",version);try{if(existsSync25(cacheDir))rmSync3(cacheDir,{recursive:!0,force:!0});copyDirSync(pluginSrc,cacheDir);let skillsSrc=join31(globalPkgDir,"skills");if(existsSync25(skillsSrc)&&!existsSync25(join31(cacheDir,"skills")))copyDirSync(skillsSrc,join31(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("\x1B[1m\uD83E\uDDDE Genie CLI Update\x1B[0m"),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"),console.log();let channel=await resolveChannel(options);if(options.next||options.stable)await persistChannel(channel);let installType=await detectInstallationType();if(log(`Detected installation: ${installType}`),log(`Channel: ${channel}${channel==="next"?" (dev builds)":" (stable)"}`),console.log(),installType==="unknown")error("No Genie CLI installation found"),console.log(),console.log("Install method not configured. Please reinstall genie:"),console.log("\x1B[36m curl -fsSL https://raw.githubusercontent.com/automagik-dev/genie/main/install.sh | bash\x1B[0m"),console.log(),process.exit(1);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);await runPostUpdateMaintenanceSafe(options,{channel,installType,primaryMethod,globalInstalls:[...globalInstalls].sort(),plugin})}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){if(!diagnosticsCtx)return;try{let diagnostics=await collectUpdateDiagnostics(diagnosticsCtx,maintenance);printDiagnosticsSummary(diagnostics)}catch(err){let msg=err instanceof Error?err.message:String(err);log(`Post-update diagnostics capture failed (non-fatal): ${msg}`)}}async function runPostUpdateMaintenanceSafe(options={},diagnosticsCtx){if(options.skipMaintenance||isTruthyEnv(process.env.GENIE_UPDATE_SKIP_MAINTENANCE)){log("Skipping post-update maintenance (requested).");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 capturePostUpdateDiagnostics(diagnosticsCtx,{outcome,durationMs:Date.now()-startedAt,lines:maintenanceLines,error:maintenanceError})}init_version();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(){process.env.GENIE_SKIP_DB_BOOT="1";let stdin=await readStdin();if(!stdin.trim())process.exit(0);let result2=await dispatch(stdin);if(result2)process.stdout.write(result2)}function registerHookNamespace(program2){program2.command("hook").description("Hook middleware for Claude Code integration").command("dispatch").description("Dispatch a CC hook event (reads JSON from stdin, writes decision to stdout)").action(dispatchAction)}init_audit();init_db();init_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 sleep3(100),await executeTmux2(`send-keys -t '${paneId}' Enter`),await sleep3(100),await executeTmux2(`send-keys -t '${paneId}' ${shellEscape(text)}`),await sleep3(100),await executeTmux2(`send-keys -t '${paneId}' Enter`)}function findCurrentOption(output){let lines=stripAnsi(output).split(`
|
|
3861
3861
|
`);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 sleep3(50);await sleep3(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 sleep3(ms){return new Promise((resolve6)=>setTimeout(resolve6,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 resolve5(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(`
|
|
3862
3862
|
(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(`
|
|
@@ -3948,7 +3948,7 @@ Registering in Omni (${omniUrl})...`);let existingId=await findOmniAgent(name);i
|
|
|
3948
3948
|
/genie:omni
|
|
3949
3949
|
|
|
3950
3950
|
`);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 agents=await(await Promise.resolve().then(() => (init_agent_registry(),exports_agent_registry))).listAgents({}),sender=agents.find((a)=>a.customName===from||a.role===from||a.id===from),recipient=agents.find((a)=>a.customName===to||a.role===to||a.id===to);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};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)),senderActor={actorType:"local",actorId:from},recipientActor={actorType:"local",actorId:to},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,to,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)),matches=(await registry.listAgents()).filter((a)=>a.customName===name||a.role===name||a.id===name),preferredTeam=process.env.GENIE_TEAM,agent=(preferredTeam&&matches.find((a)=>a.team===preferredTeam))??matches[0];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(`
|
|
3951
|
-
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),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:existsSync47}=await import("fs"),{join:join58,dirname:
|
|
3951
|
+
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),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:existsSync47}=await import("fs"),{join:join58,dirname:dirname16}=await import("path"),{execSync:execSync11}=await import("child_process"),appName="genie-desktop",rootDir=join58(dirname16(new URL(import.meta.url).pathname),"..",".."),localBin=[join58(rootDir,"packages","genie-app","src-tauri","target","release","genie-desktop"),join58(rootDir,"packages","genie-app","src-tauri","target","debug","genie-desktop"),join58(rootDir,"dist","app","genie-desktop"),"/usr/local/bin/genie-desktop"].find((p)=>existsSync47(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:execFileSync2}=await import("child_process");try{execFileSync2(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
|
|
3952
3952
|
`),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 row of rows){let timeout=new Date(row.timeout_at).toLocaleTimeString();console.log(` ${String(row.id).padEnd(38)} ${String(row.agent_name).padEnd(20)} ${String(row.tool_name).padEnd(15)} ${timeout}`)}console.log(`
|
|
3953
3953
|
${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=`
|
|
3954
3954
|
id,
|
|
@@ -4091,15 +4091,15 @@ Registering in Omni (${omniUrl})...`);let existingId=await findOmniAgent(name);i
|
|
|
4091
4091
|
(${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,(row)=>{if(options.json)console.log(JSON.stringify(row));else{let time=formatRelativeTimestamp(row.created_at),entity=`${row.entity_type}:${row.entity_id}`.slice(0,40),event=row.event_type.padEnd(24),details=summarizeDetails(row.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},(row)=>{if(!options.all&&!options.type&&DEFAULT_HIDDEN_EVENT_TYPES.has(row.event_type))return;if(options.json){console.log(JSON.stringify({stream:"audit",...row}));return}console.log(formatEventLine2(clockTime(row.created_at),renderAuditEvent2({entity_type:row.entity_type,entity_id:row.entity_id,event_type:row.event_type,details:row.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((row)=>row[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 row of data)console.log(row.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(`
|
|
4092
4092
|
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((row)=>row[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 row of data)console.log(row.map((v,i2)=>padRight(v.slice(0,widths[i2]),widths[i2])).join(" | "));console.log(`
|
|
4093
4093
|
(${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((row)=>row[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 row of data)console.log(row.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(`
|
|
4094
|
-
(${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:spawnSync7}=__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=spawnSync7("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 migrateCommand(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 existsSync48,mkdirSync as mkdirSync20,readFileSync as readFileSync30,writeFileSync as writeFileSync20}from"fs";import{dirname as dirname15,join as join59}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(`
|
|
4094
|
+
(${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:spawnSync7}=__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=spawnSync7("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 migrateCommand(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 existsSync48,mkdirSync as mkdirSync20,readFileSync as readFileSync30,writeFileSync as writeFileSync20}from"fs";import{dirname as dirname16,join as join59}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(`
|
|
4095
4095
|
${boards.length} board${boards.length===1?"":"s"}`)}function printColumnPipeline(columns,header){console.log(`
|
|
4096
4096
|
${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(`
|
|
4097
4097
|
${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(`
|
|
4098
4098
|
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(`
|
|
4099
4099
|
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=join59(repoRoot,".genie"),configPath2=join59(genieDir,"config.json");if(!existsSync48(genieDir))mkdirSync20(genieDir,{recursive:!0});let config={};if(existsSync48(configPath2))try{config=JSON.parse(readFileSync30(configPath2,"utf-8"))}catch{}config.activeBoard=board.id,writeFileSync20(configPath2,`${JSON.stringify(config,null,2)}
|
|
4100
|
-
`),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=
|
|
4100
|
+
`),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=dirname16(options.output);if(!existsSync48(dir))mkdirSync20(dir,{recursive:!0});writeFileSync20(options.output,`${json2}
|
|
4101
4101
|
`),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=readFileSync30(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(`
|
|
4102
|
-
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 existsSync49,mkdirSync as mkdirSync21,readFileSync as readFileSync31,realpathSync as realpathSync6,writeFileSync as writeFileSync21}from"fs";import{homedir as homedir39}from"os";import{dirname as dirname16,join as join60,resolve as resolve11}from"path";var BRAIN_PKG2="@khal-os/brain",BRAIN_REPO="khal-os/brain";function resolveGenieRoot(){try{let scriptDir=dirname16(realpathSync6(process.argv[1])),candidates=[resolve11(scriptDir,".."),resolve11(scriptDir,"..","..")];for(let c of candidates)if(existsSync49(join60(c,"package.json")))return c}catch{}return resolve11(import.meta.dir,"..","..")}var BRAIN_DIR2=join60(resolveGenieRoot(),"node_modules","@khal-os","brain"),CACHE_PATH=join60(homedir39(),".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(readFileSync31(join60(BRAIN_DIR2,"package.json"),"utf-8")).version??"unknown"}catch{return}}function resolveBrainBin(){let candidates=[join60(resolveGenieRoot(),"node_modules",".bin","brain"),join60(BRAIN_DIR2,"dist","cli.js")];for(let c of candidates)if(existsSync49(c))return c;return}function readActiveBrainConfig(){try{let configPath2=join60(homedir39(),".brain","config.json");if(!existsSync49(configPath2))return null;let data=JSON.parse(readFileSync31(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=join60(brainPath,".brain-server.json");return JSON.parse(readFileSync31(serverJsonPath,"utf-8")).args}catch{return}}function checkForUpdates(cachePath){try{let p=cachePath??CACHE_PATH;if(!existsSync49(p))return{updateAvailable:!1};let cache=JSON.parse(readFileSync31(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=join60(homedir39(),".genie");mkdirSync21(cacheDir,{recursive:!0}),writeFileSync21(CACHE_PATH,JSON.stringify({checkedAt:new Date().toISOString(),localVersion:version,latestTag,latestVersion,updateAvailable},null,2))}catch{}}async function updateBrain(){if(!existsSync49(join60(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=join60(homedir39(),".cache","genie-brain");mkdirSync21(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"}),mkdirSync21(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(`
|
|
4102
|
+
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 existsSync49,mkdirSync as mkdirSync21,readFileSync as readFileSync31,realpathSync as realpathSync6,writeFileSync as writeFileSync21}from"fs";import{homedir as homedir39}from"os";import{dirname as dirname17,join as join60,resolve as resolve11}from"path";var BRAIN_PKG2="@khal-os/brain",BRAIN_REPO="khal-os/brain";function resolveGenieRoot(){try{let scriptDir=dirname17(realpathSync6(process.argv[1])),candidates=[resolve11(scriptDir,".."),resolve11(scriptDir,"..","..")];for(let c of candidates)if(existsSync49(join60(c,"package.json")))return c}catch{}return resolve11(import.meta.dir,"..","..")}var BRAIN_DIR2=join60(resolveGenieRoot(),"node_modules","@khal-os","brain"),CACHE_PATH=join60(homedir39(),".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(readFileSync31(join60(BRAIN_DIR2,"package.json"),"utf-8")).version??"unknown"}catch{return}}function resolveBrainBin(){let candidates=[join60(resolveGenieRoot(),"node_modules",".bin","brain"),join60(BRAIN_DIR2,"dist","cli.js")];for(let c of candidates)if(existsSync49(c))return c;return}function readActiveBrainConfig(){try{let configPath2=join60(homedir39(),".brain","config.json");if(!existsSync49(configPath2))return null;let data=JSON.parse(readFileSync31(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=join60(brainPath,".brain-server.json");return JSON.parse(readFileSync31(serverJsonPath,"utf-8")).args}catch{return}}function checkForUpdates(cachePath){try{let p=cachePath??CACHE_PATH;if(!existsSync49(p))return{updateAvailable:!1};let cache=JSON.parse(readFileSync31(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=join60(homedir39(),".genie");mkdirSync21(cacheDir,{recursive:!0}),writeFileSync21(CACHE_PATH,JSON.stringify({checkedAt:new Date().toISOString(),localVersion:version,latestTag,latestVersion,updateAvailable},null,2))}catch{}}async function updateBrain(){if(!existsSync49(join60(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=join60(homedir39(),".cache","genie-brain");mkdirSync21(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"}),mkdirSync21(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(`
|
|
4103
4103
|
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=join60(root,"node_modules","@khal-os","brain"),tmpDir=join60(homedir39(),".cache","genie-brain");mkdirSync21(tmpDir,{recursive:!0}),execSync12(`gh release download ${tag} --repo ${BRAIN_REPO} --pattern '*.tgz' --dir "${tmpDir}" --clobber`,{stdio:"inherit"}),execSync12(`rm -rf "${brainDir}"`,{stdio:"pipe"}),mkdirSync21(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(`
|
|
4104
4104
|
`)[0]}). Run manually: brain install --apply --yes`)}}async function uninstallBrain(){try{if(!existsSync49(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(`
|
|
4105
4105
|
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",`
|
|
@@ -4160,7 +4160,7 @@ Genie Scheduler Daemon`),console.log("\u2500".repeat(50)),console.log(` Status:
|
|
|
4160
4160
|
(showing last ${lines} of ${allLines.length} entries)`)}async function tailFollow(filePath,initialLines){let{watch:watch2}=await import("fs");tailStatic(filePath,initialLines),console.log(`
|
|
4161
4161
|
--- following (Ctrl+C to exit) ---
|
|
4162
4162
|
`);let lastSize=existsSync50(filePath)?readFileSync32(filePath).length:0,watcher2=watch2(filePath,()=>{try{let content=readFileSync32(filePath,"utf-8");if(content.length>lastSize){let newLines=content.slice(lastSize).trim().split(`
|
|
4163
|
-
`).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 existsSync52,readFileSync as readFileSync34}from"fs";import{dirname as
|
|
4163
|
+
`).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 existsSync52,readFileSync as readFileSync34}from"fs";import{dirname as dirname18,join as join63}from"path";import{createInterface as createInterface3}from"readline";init_db();init_wish_state();import{spawnSync as spawnSync7}from"child_process";import{existsSync as existsSync51,mkdirSync as mkdirSync23,readFileSync as readFileSync33,renameSync as renameSync7,statSync as statSync11,writeFileSync as writeFileSync23}from"fs";import{homedir as homedir41}from"os";import{basename as basename11,join as join62,relative as relative4,resolve as resolve12}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??join62(homedir41(),".genie");return join62(genieHome6,"backups",basename11(repoRoot),SNAPSHOT_FILE)}function assertOutsideRepo(snapshotPath,cwd){let repoRoot=resolveRepoPath(cwd),rel=relative4(repoRoot,resolve12(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`;mkdirSync23(snapshotDir,{recursive:!0});let result2=spawnSync7("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);writeFileSync23(tmpPath,compressed),renameSync7(tmpPath,snapshotPath);let compressedBytes=statSync11(snapshotPath).size,uncompressedBytes=0;try{let sizeResult=spawnSync7("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(!existsSync51(filePath))throw Error(`Snapshot not found: ${filePath}`);let env=pgEnv();spawnSync7("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=readFileSync33(filePath),sql=gunzipSync(compressed),restoreResult=spawnSync7("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();function findNearestPackageJson(start3){let cwd=start3;while(!0){let candidate=join63(cwd,"package.json");if(existsSync52(candidate))return candidate;let parent=dirname18(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(readFileSync34(path3,"utf8"))?.pgserve?.persist===!0}catch{return!1}}function printTable(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 row of rows){let line=columns.map((col,i2)=>padRight(String(row[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(`
|
|
4164
4164
|
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(`
|
|
4165
4165
|
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(`
|
|
4166
4166
|
Migrations: ${migrations.applied.length} applied, ${migrations.pending.length} pending`);let tables=await sql`
|
|
@@ -4178,8 +4178,8 @@ Done. ${results.length} migration${results.length===1?"":"s"} applied.`),await s
|
|
|
4178
4178
|
`,count=Number(rows[0].cnt);console.log(`Would delete ${count} event${count===1?"":"s"} older than ${options.olderThan}.`)}else{let result2=await sql`
|
|
4179
4179
|
DELETE FROM genie_runtime_events
|
|
4180
4180
|
WHERE created_at < now() - make_interval(secs => ${intervalSec})
|
|
4181
|
-
`,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)}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 existsSync59,mkdirSync as mkdirSync24,writeFileSync as writeFileSync24}from"fs";import{dirname as
|
|
4182
|
-
`);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 readFileSync36}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 row of rows){let conditions=pk.map((col,i2)=>`${col} = $${i2+1}`).join(" AND "),values2=pk.map((col)=>row[col]);if((await sql.unsafe(`SELECT 1 FROM ${table} WHERE ${conditions} LIMIT 1`,values2)).length>0)conflicts.push(row)}return conflicts}function prepareRow(row,table,selfRefUpdates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],entries=Object.entries(row),columns=entries.map(([k])=>k),values2=entries.map(([,v])=>v);for(let col of columns)assertValidColumnName(col);if(selfRefCol&&row[selfRefCol]!=null){let idx=columns.indexOf(selfRefCol);if(idx!==-1){let originalSelfRef=values2[idx];values2[idx]=null;let pk=getPrimaryKey(table);selfRefUpdates.push({pk:pk.length===1?row[pk[0]]:pk.map((k)=>row[k]),value:originalSelfRef})}}return{columns,values:values2,quotedCols:columns.map((c)=>`"${c}"`).join(", "),placeholders:values2.map((_,i2)=>`$${i2+1}`).join(", ")}}async function insertOneRow(tx,table,row,prepared,mode){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)=>row[col]);await tx.unsafe(`DELETE FROM ${table} WHERE ${pkCondition}`,pkValues),await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}else if(mode==="merge"){let onConflict=pk.map((c)=>`"${c}"`).join(", ");await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders}) ON CONFLICT (${onConflict}) DO NOTHING`,values2)}else await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}async function updateSelfRefs(tx,table,updates){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 row of rows){let prepared=prepareRow(row,table,selfRefUpdates);await insertOneRow(tx,table,row,prepared,mode)}if(selfRefUpdates.length>0)await updateSelfRefs(tx,table,selfRefUpdates);return rows.length}function parseExportFile(filePath){let raw=readFileSync36(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 existsSync63,mkdirSync as mkdirSync27,symlinkSync,writeFileSync as writeFileSync27}from"fs";import{basename as basename12,join as join74,relative as relative7,resolve as resolve14,sep as sep2}from"path";import{cpSync,existsSync as existsSync61,mkdirSync as mkdirSync25,renameSync as renameSync8,rmSync as rmSync4}from"fs";import{join as join71,relative as relative6}from"path";var import_ignore=__toESM(require_ignore(),1);import{existsSync as existsSync60,readFileSync as readFileSync37,readdirSync as readdirSync12,statSync as statSync12}from"fs";import{join as join70,relative as relative5}from"path";var GENIEIGNORE_DEFAULTS=`node_modules
|
|
4181
|
+
`,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)}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 existsSync59,mkdirSync as mkdirSync24,writeFileSync as writeFileSync24}from"fs";import{dirname as dirname20}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=dirname20(options.output);if(!existsSync59(dir))mkdirSync24(dir,{recursive:!0});writeFileSync24(options.output,`${json2}
|
|
4182
|
+
`);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 readFileSync36}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 row of rows){let conditions=pk.map((col,i2)=>`${col} = $${i2+1}`).join(" AND "),values2=pk.map((col)=>row[col]);if((await sql.unsafe(`SELECT 1 FROM ${table} WHERE ${conditions} LIMIT 1`,values2)).length>0)conflicts.push(row)}return conflicts}function prepareRow(row,table,selfRefUpdates){let selfRefCol=SELF_REFERENTIAL_COLUMNS[table],entries=Object.entries(row),columns=entries.map(([k])=>k),values2=entries.map(([,v])=>v);for(let col of columns)assertValidColumnName(col);if(selfRefCol&&row[selfRefCol]!=null){let idx=columns.indexOf(selfRefCol);if(idx!==-1){let originalSelfRef=values2[idx];values2[idx]=null;let pk=getPrimaryKey(table);selfRefUpdates.push({pk:pk.length===1?row[pk[0]]:pk.map((k)=>row[k]),value:originalSelfRef})}}return{columns,values:values2,quotedCols:columns.map((c)=>`"${c}"`).join(", "),placeholders:values2.map((_,i2)=>`$${i2+1}`).join(", ")}}async function insertOneRow(tx,table,row,prepared,mode){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)=>row[col]);await tx.unsafe(`DELETE FROM ${table} WHERE ${pkCondition}`,pkValues),await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}else if(mode==="merge"){let onConflict=pk.map((c)=>`"${c}"`).join(", ");await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders}) ON CONFLICT (${onConflict}) DO NOTHING`,values2)}else await tx.unsafe(`INSERT INTO ${table} (${quotedCols}) VALUES (${placeholders})`,values2)}async function updateSelfRefs(tx,table,updates){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 row of rows){let prepared=prepareRow(row,table,selfRefUpdates);await insertOneRow(tx,table,row,prepared,mode)}if(selfRefUpdates.length>0)await updateSelfRefs(tx,table,selfRefUpdates);return rows.length}function parseExportFile(filePath){let raw=readFileSync36(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 existsSync63,mkdirSync as mkdirSync27,symlinkSync,writeFileSync as writeFileSync27}from"fs";import{basename as basename13,join as join74,relative as relative7,resolve as resolve14,sep as sep2}from"path";import{cpSync,existsSync as existsSync61,mkdirSync as mkdirSync25,renameSync as renameSync8,rmSync as rmSync4}from"fs";import{join as join71,relative as relative6}from"path";var import_ignore=__toESM(require_ignore(),1);import{existsSync as existsSync60,readFileSync as readFileSync37,readdirSync as readdirSync12,statSync as statSync12}from"fs";import{join as join70,relative as relative5}from"path";var GENIEIGNORE_DEFAULTS=`node_modules
|
|
4183
4183
|
.git
|
|
4184
4184
|
.genie/worktrees
|
|
4185
4185
|
dist
|
|
@@ -4202,8 +4202,8 @@ coverage
|
|
|
4202
4202
|
`),writeFileSync27(join74(agentDir,"brain","memory","MEMORY.md"),`# Memory Index
|
|
4203
4203
|
|
|
4204
4204
|
_This file is maintained by the auto-memory system. New memories are added automatically._
|
|
4205
|
-
`);let reposTarget=join74(workspaceRoot,"repos");if(existsSync63(reposTarget))try{symlinkSync(reposTarget,join74(agentDir,"repos"))}catch{}if(console.log(`Agent scaffolded: agents/${name}/`),console.log(" AGENTS.md, SOUL.md, HEARTBEAT.md"),console.log(" brain/memory/MEMORY.md (seeded)"),console.log(" .claude/settings.local.json (auto-memory enabled)"),existsSync63(join74(agentDir,"repos")))console.log(" repos -> ../repos (symlink)")}async function maybeBootstrapDefaultAgent(workspaceRoot){if(scanAgents(workspaceRoot).length>0)return!1;if(!await esm_default4({message:"No agent found in this workspace. Scaffold the default `genie` agent now?",default:!0}))return console.log(" Skipped default agent bootstrap. Run `genie init agent genie` later."),!1;return scaffoldAgentInWorkspace(workspaceRoot,"genie"),!0}async function syncWorkspaceAgents(workspaceRoot){let agents=scanAgents(workspaceRoot);if(agents.length===0)return;console.log(` Found ${agents.length} agent(s): ${agents.join(", ")}`);try{let{syncAgentDirectory:syncAgentDirectory2}=await Promise.resolve().then(() => (init_agent_sync(),exports_agent_sync)),result2=await syncAgentDirectory2(workspaceRoot);if(result2.registered.length>0)console.log(` Registered: ${result2.registered.join(", ")}`);if(result2.updated.length>0)console.log(` Updated: ${result2.updated.join(", ")}`)}catch{}}async function initWorkspace(){let cwd=process.cwd(),existing=findWorkspace(cwd);if(existing){if(console.log(`Already inside workspace: ${existing.root}`),await maybeBootstrapDefaultAgent(existing.root))await syncWorkspaceAgents(existing.root);return}let genieDir=join74(cwd,".genie");mkdirSync27(genieDir,{recursive:!0});let pgUrl=detectPgUrl(),config={name:
|
|
4206
|
-
`);let genieignorePath=join74(cwd,".genieignore");if(!existsSync63(genieignorePath))writeFileSync27(genieignorePath,GENIEIGNORE_DEFAULTS,"utf-8"),console.log(" Created .genieignore");if(console.log(`Workspace created: ${cwd}`),pgUrl)console.log(` pgUrl: ${pgUrl}`);await maybeBootstrapDefaultAgent(cwd),await syncWorkspaceAgents(cwd),await runPostInitFlow(cwd,config)}async function runPostInitFlow(workspaceRoot,config){if(!isInteractive())return;let discovered=await discoverExternalAgents(workspaceRoot);refreshPending(workspaceRoot,discovered);let pending=listPending(workspaceRoot),ctx={workspaceRoot,workspaceName:
|
|
4205
|
+
`);let reposTarget=join74(workspaceRoot,"repos");if(existsSync63(reposTarget))try{symlinkSync(reposTarget,join74(agentDir,"repos"))}catch{}if(console.log(`Agent scaffolded: agents/${name}/`),console.log(" AGENTS.md, SOUL.md, HEARTBEAT.md"),console.log(" brain/memory/MEMORY.md (seeded)"),console.log(" .claude/settings.local.json (auto-memory enabled)"),existsSync63(join74(agentDir,"repos")))console.log(" repos -> ../repos (symlink)")}async function maybeBootstrapDefaultAgent(workspaceRoot){if(scanAgents(workspaceRoot).length>0)return!1;if(!await esm_default4({message:"No agent found in this workspace. Scaffold the default `genie` agent now?",default:!0}))return console.log(" Skipped default agent bootstrap. Run `genie init agent genie` later."),!1;return scaffoldAgentInWorkspace(workspaceRoot,"genie"),!0}async function syncWorkspaceAgents(workspaceRoot){let agents=scanAgents(workspaceRoot);if(agents.length===0)return;console.log(` Found ${agents.length} agent(s): ${agents.join(", ")}`);try{let{syncAgentDirectory:syncAgentDirectory2}=await Promise.resolve().then(() => (init_agent_sync(),exports_agent_sync)),result2=await syncAgentDirectory2(workspaceRoot);if(result2.registered.length>0)console.log(` Registered: ${result2.registered.join(", ")}`);if(result2.updated.length>0)console.log(` Updated: ${result2.updated.join(", ")}`)}catch{}}async function initWorkspace(){let cwd=process.cwd(),existing=findWorkspace(cwd);if(existing){if(console.log(`Already inside workspace: ${existing.root}`),await maybeBootstrapDefaultAgent(existing.root))await syncWorkspaceAgents(existing.root);return}let genieDir=join74(cwd,".genie");mkdirSync27(genieDir,{recursive:!0});let pgUrl=detectPgUrl(),config={name:basename13(cwd),pgUrl,agents:{defaults:{}},tmux:{socket:"genie"},sdk:{}};writeFileSync27(join74(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
|
|
4206
|
+
`);let genieignorePath=join74(cwd,".genieignore");if(!existsSync63(genieignorePath))writeFileSync27(genieignorePath,GENIEIGNORE_DEFAULTS,"utf-8"),console.log(" Created .genieignore");if(console.log(`Workspace created: ${cwd}`),pgUrl)console.log(` pgUrl: ${pgUrl}`);await maybeBootstrapDefaultAgent(cwd),await syncWorkspaceAgents(cwd),await runPostInitFlow(cwd,config)}async function runPostInitFlow(workspaceRoot,config){if(!isInteractive())return;let discovered=await discoverExternalAgents(workspaceRoot);refreshPending(workspaceRoot,discovered);let pending=listPending(workspaceRoot),ctx={workspaceRoot,workspaceName:basename13(workspaceRoot),config,discovered,pending,canonicalAgentCount:scanAgents(workspaceRoot).length},result2=await runMiniWizard(ctx);if(result2.importedAgents.length>0){let toImport=pending.filter((p)=>result2.importedAgents.includes(p.name)),discoveredToImport=toImport.map((p)=>({name:p.name,path:p.path,relativePath:p.relativePath,isSubAgent:p.isSubAgent,parentName:p.parentName})),importResult=importAgents(workspaceRoot,discoveredToImport);for(let name of importResult.imported){let agent=toImport.find((a)=>a.name===name);if(agent)removePending(workspaceRoot,agent.path);console.log(` Imported: ${name}`)}for(let err of importResult.errors)console.error(` Import failed (${err.name}): ${err.error}`);await syncWorkspaceAgents(workspaceRoot)}}function resolveAgentsDir(wsRoot,dirOption){if(dirOption)return resolve14(dirOption);let cwd=process.cwd(),rel=relative7(wsRoot,cwd);if(rel.startsWith(".."))return join74(wsRoot,"agents");let segments=rel===""?[]:rel.split(sep2),idx=segments.indexOf("agents");if(idx===-1)return join74(wsRoot,"agents");return join74(wsRoot,...segments.slice(0,idx+1))}async function initAgent(name,options){if(!name||/[\/\\]/.test(name)||name==="."||name===".."||name.includes(".."))console.error("Error: Agent name must not contain path separators or traversal sequences."),process.exit(1);let cwd=process.cwd(),ws=findWorkspace(cwd);if(!ws)console.error("Error: Not in a genie workspace. Run `genie init` first."),process.exit(1);let agentsDir=resolveAgentsDir(ws.root,options.dir);try{scaffoldAgentInWorkspace(ws.root,name,agentsDir)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function registerInitCommands(program2){program2.command("init").description("Initialize a genie workspace").action(async()=>{await ensureSetupCompleteForInit(),await initWorkspace()}).command("agent <name>").description("Scaffold a new agent in the workspace").option("--dir <path>","Target directory for agent (default: CWD if inside agents/, else workspace agents/)").action(async(name,options)=>{await ensureSetupCompleteForInit(),await initAgent(name,options)})}init_db();init_runtime_events();init_term_format();function parseSince4(since){let match=since.match(/^(\d+)([smhd])$/);if(!match)return since;let amount=Number.parseInt(match[1],10),unit=match[2],ms={s:1000,m:60000,h:3600000,d:86400000}[unit]??3600000;return new Date(Date.now()-amount*ms).toISOString()}async function metricsNowCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),snapshots=await sql`SELECT * FROM machine_snapshots ORDER BY created_at DESC LIMIT 1`,agentCount=await sql`SELECT count(DISTINCT agent_id)::int as cnt FROM executors WHERE state NOT IN ('done', 'error', 'terminated')`,teamCount=await sql`SELECT count(*)::int as cnt FROM teams WHERE status = 'in_progress'`,snapshot=snapshots[0]??{},throughput=await queryRuntimeEventThroughput(60),data={active_workers:snapshot.active_workers??agentCount[0]?.cnt??0,active_teams:snapshot.active_teams??teamCount[0]?.cnt??0,tmux_sessions:snapshot.tmux_sessions??0,cpu_percent:snapshot.cpu_percent??null,memory_mb:snapshot.memory_mb??null,snapshot_at:snapshot.created_at?new Date(snapshot.created_at).toISOString():null,events_emitted_last_60s:throughput.emitted};if(options.json){console.log(JSON.stringify(data,null,2));return}if(console.log("Machine State:"),console.log(` Workers: ${data.active_workers}`),console.log(` Teams: ${data.active_teams}`),console.log(` Tmux: ${data.tmux_sessions} sessions`),data.cpu_percent!==null)console.log(` CPU: ${data.cpu_percent}%`);if(data.memory_mb!==null)console.log(` Memory: ${data.memory_mb} MB`);if(data.snapshot_at)console.log(` As of: ${formatRelativeTimestamp(data.snapshot_at)}`);console.log(`
|
|
4207
4207
|
Event Throughput (last 60s):`),console.log(` Emitted: ${data.events_emitted_last_60s}`)}async function metricsHistoryCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),sinceTs=parseSince4(options.since??"1h"),rows=await sql`
|
|
4208
4208
|
SELECT active_workers, active_teams, tmux_sessions, cpu_percent, memory_mb, created_at
|
|
4209
4209
|
FROM machine_snapshots
|
|
@@ -4211,7 +4211,7 @@ Event Throughput (last 60s):`),console.log(` Emitted: ${data.events_emitted_la
|
|
|
4211
4211
|
ORDER BY created_at ASC
|
|
4212
4212
|
`;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((row)=>row[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 row of data)console.log(row.map((v,i2)=>padRight(v,widths[i2])).join(" | "));console.log(`
|
|
4213
4213
|
(${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(`
|
|
4214
|
-
${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_genie_config2();import{generateKeyPairSync}from"crypto";import{chmodSync as chmodSync3,existsSync as existsSync64,mkdirSync as mkdirSync28,readFileSync as readFileSync40,writeFileSync as writeFileSync28}from"fs";import{hostname as osHostname}from"os";import{dirname as
|
|
4214
|
+
${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_genie_config2();import{generateKeyPairSync}from"crypto";import{chmodSync as chmodSync3,existsSync as existsSync64,mkdirSync as mkdirSync28,readFileSync as readFileSync40,writeFileSync as writeFileSync28}from"fs";import{hostname as osHostname}from"os";import{dirname as dirname21,join as join75,resolve as resolvePath4}from"path";function keyPaths2(){let home=process.env.GENIE_HOME??join75(process.env.HOME??"/root",".genie"),dir=join75(home,"keys");return{dir,privateKey:join75(dir,"genie-host.ed25519"),publicKey:join75(dir,"genie-host.ed25519.pub"),hostJson:join75(dir,"host.json")}}function assertNotInsideGitRepo(dir){let probe=resolvePath4(dir);for(let depth=0;depth<16;depth++){if(existsSync64(join75(probe,".git")))throw Error(`Refusing to write keys to ${dir} \u2014 it lives inside a git working tree (${join75(probe,".git")}). Set $GENIE_HOME to a path outside any git repo and re-run.`);let parent=dirname21(probe);if(parent===probe)return;probe=parent}}function generateAndPersistKeypair(paths){if(!existsSync64(paths.dir))mkdirSync28(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 writeFileSync28(paths.privateKey,privateKey.export({format:"pem",type:"pkcs8"}),{mode:384}),writeFileSync28(paths.publicKey,pubkeyB64Url,{mode:420}),chmodSync3(paths.privateKey,384),{pubkeyB64Url}}function loadExistingPubkey(paths){if(!existsSync64(paths.publicKey))return null;return readFileSync40(paths.publicKey,"utf-8").trim()}function loadHostJson(paths){if(!existsSync64(paths.hostJson))return null;try{return JSON.parse(readFileSync40(paths.hostJson,"utf-8"))}catch{return null}}function writeHostJson(paths,record){writeFileSync28(paths.hostJson,`${JSON.stringify(record,null,2)}
|
|
4215
4215
|
`,{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(`
|
|
4216
4216
|
\u26A0 Rotated key registered as ${host.id}, but revoking the old host (${previousRecord.hostId}) failed:
|
|
4217
4217
|
${message}
|
|
@@ -4221,8 +4221,8 @@ Event Throughput (last 60s):`),console.log(` Emitted: ${data.events_emitted_la
|
|
|
4221
4221
|
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(`
|
|
4222
4222
|
By status:`);for(let[status,count]of Object.entries(byStatus).sort())console.log(` ${padRight(status,15)} ${count}`);console.log(`
|
|
4223
4223
|
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();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 runDryRun(ttlHours){let zombies=await listExhaustedZombies(ttlHours);if(zombies.length===0){console.log(`No exhausted zombies older than ${ttlHours}h.`);return}let plural=zombies.length===1?"":"s";console.log(`Would archive ${zombies.length} zombie agent${plural} older than ${ttlHours}h:`);for(let z of zombies)console.log(` ${z.id} (last state change: ${z.lastStateChange})`)}async function runArchive(ttlHours){let ids=await archiveExhaustedZombies(ttlHours);if(ids.length===0){console.log(`No exhausted zombies older than ${ttlHours}h. Nothing to archive.`);return}let plural=ids.length===1?"":"s";console.log(`Archived ${ids.length} zombie agent${plural} older than ${ttlHours}h:`);for(let id of ids)console.log(` ${id}`)}async function pruneCommand(options){if(!options.zombies)console.error("Error: no prune target specified. Use `--zombies`."),console.error("See `genie prune --help` for available targets."),process.exit(2);let ttlHours=options.ttlHours??24;if(!await isAvailable())console.error("Database is not running. Start it with: genie db status"),process.exit(1);try{await(options.dryRun?runDryRun(ttlHours):runArchive(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 dead-pane zombies whose auto-resume retries are exhausted").option("--dry-run","List targets that would be affected without mutating").option("--ttl-hours <hours>","Minimum age in hours before a zombie is eligible for archive (default: 24)",(v)=>parsePositiveInt(v,"--ttl-hours")).action(pruneCommand)}init_agent_registry();import{readFile as readFile16,stat as stat10}from"fs/promises";import{join as join78}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(`
|
|
4224
|
-
`),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 rm4,writeFile as writeFile10}from"fs/promises";import{tmpdir as tmpdir4}from"os";import{dirname as
|
|
4225
|
-
`)}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(status,parts,index){if(status.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:status.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 status=parts[i2++]??"";if(!status)break;let{op,nextIndex}=parseStatusEntry(status,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 rm4(join77(worktreePath,op.path),{recursive:!0,force:!0});continue}if(op.kind==="rename"){await rm4(join77(worktreePath,op.from),{recursive:!0,force:!0});let src2=join77(repoPath,op.to),dest2=join77(worktreePath,op.to);await mkdir11(
|
|
4224
|
+
`),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 rm4,writeFile as writeFile10}from"fs/promises";import{tmpdir as tmpdir4}from"os";import{dirname as dirname22,join as join77,resolve as resolve16}from"path";var{$:$4}=globalThis.Bun;import{createHash as createHash8}from"crypto";import{mkdir as mkdir10,readFile as readFile15,readdir as readdir10,stat as stat9,writeFile as writeFile9}from"fs/promises";import{homedir as homedir43}from"os";import{join as join76,relative as relative8,resolve as resolve15}from"path";function repoHash(repoPath){return createHash8("sha256").update(resolve15(repoPath)).digest("hex").slice(0,12)}function resultsDir(repoPath){let base=process.env.GENIE_HOME??join76(homedir43(),".genie");return join76(base,"qa",repoHash(repoPath))}function resultsPath(repoPath){return join76(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,report){let dir=resultsDir(repoPath);await mkdir10(dir,{recursive:!0});let results=await loadResults(repoPath),specHash=await hashSpecFile(report.file);results[specKey]={lastRun:new Date().toISOString(),result:report.result,durationMs:report.durationMs,specHash,expectations:report.expectations,error:report.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 createHash8("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=join76(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)}
|
|
4225
|
+
`)}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(status,parts,index){if(status.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:status.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 status=parts[i2++]??"";if(!status)break;let{op,nextIndex}=parseStatusEntry(status,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 rm4(join77(worktreePath,op.path),{recursive:!0,force:!0});continue}if(op.kind==="rename"){await rm4(join77(worktreePath,op.from),{recursive:!0,force:!0});let src2=join77(repoPath,op.to),dest2=join77(worktreePath,op.to);await mkdir11(dirname22(dest2),{recursive:!0}),await cp2(src2,dest2,{recursive:!0,force:!0});continue}let src=join77(repoPath,op.path),dest=join77(worktreePath,op.path);await mkdir11(dirname22(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(`
|
|
4226
4226
|
[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=join77(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,report,ndjson){await emitQaEvent(repoPath,"spec-done",{type:"qa:spec-done",specKey,domain,team,result:report.result,durationMs:report.durationMs,expectations:report.expectations,error:report.error},ndjson)}async function runSpecEntries(entries,specDir,options){let repoPath=resolve16(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(`
|
|
4227
4227
|
[qa] Running ${prepared.length} specs (max ${maxConcurrency} parallel)
|
|
4228
4228
|
`);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(report)=>{let key=specKeyFromPath(specDir,p.entry.filePath);await saveResult(repoPath,key,report);let icon=report.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} (${(report.durationMs/1000).toFixed(0)}s) [${elapsed}s total]`),await emitSpecDone(repoPath,p.entry.key,p.entry.domain,p.teamName,report,ndjson),reports.push(report)}).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(`
|
|
@@ -4376,9 +4376,9 @@ Team: ${teamName}
|
|
|
4376
4376
|
LIMIT ${limit}
|
|
4377
4377
|
`;if(rows.length===0){console.log(`No execution history for schedule "${schedule.name}"`),await shutdown();return}console.log(`
|
|
4378
4378
|
History for "${schedule.name}":
|
|
4379
|
-
`);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):"-"]);printTable2(["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 spawnSync8}from"child_process";import{existsSync as existsSync65,readFileSync as readFileSync41,readdirSync as readdirSync13,realpathSync as realpathSync7}from"fs";import{dirname as
|
|
4379
|
+
`);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):"-"]);printTable2(["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 spawnSync8}from"child_process";import{existsSync as existsSync65,readFileSync as readFileSync41,readdirSync as readdirSync13,realpathSync as realpathSync7}from"fs";import{dirname as dirname23,join as join79,resolve as resolve17}from"path";var defaultDeps5={existsSync:existsSync65,realpathSync:realpathSync7,readFileSync:(path3,encoding)=>readFileSync41(path3,encoding),spawnSync:(command,args,options)=>spawnSync8(command,args,options),setExitCode:(exitCode)=>{process.exitCode=exitCode},stdout:(line)=>process.stdout.write(`${line}
|
|
4380
4380
|
`),stderr:(line)=>process.stderr.write(`${line}
|
|
4381
|
-
`),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=dirname22(deps.realpathSync(argv1)),candidates=[resolve17(scriptDir,".."),resolve17(scriptDir,"..","..")];for(let candidate of candidates)if(deps.existsSync(join79(candidate,"package.json")))return candidate}}catch{}return resolve17(import.meta.dir,"..","..")}function resolveSecScanScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join79(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=join79(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=join79(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 readdirSync13(bundleDir))if(entry2.endsWith(".tgz"))candidates.push(entry2)}catch{return null}for(let tarballName of candidates){let tarball=join79(bundleDir,tarballName),signature=`${tarball}.sig`,certificate=`${tarball}.cert`;if(!deps.existsSync(signature))continue;if(!deps.existsSync(certificate))continue;let provenancePath=join79(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 dirname22(resolve17(options.tarball));return resolve17(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(join79(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,status=json2.verified?"OK":"FAIL";if(deps.stdout(`verify-install: ${status} (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",`
|
|
4381
|
+
`),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=dirname23(deps.realpathSync(argv1)),candidates=[resolve17(scriptDir,".."),resolve17(scriptDir,"..","..")];for(let candidate of candidates)if(deps.existsSync(join79(candidate,"package.json")))return candidate}}catch{}return resolve17(import.meta.dir,"..","..")}function resolveSecScanScript(argv1=process.argv[1],deps=defaultDeps5){let root=resolveGenieRoot2(argv1,deps),scriptPath=join79(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=join79(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=join79(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 readdirSync13(bundleDir))if(entry2.endsWith(".tgz"))candidates.push(entry2)}catch{return null}for(let tarballName of candidates){let tarball=join79(bundleDir,tarballName),signature=`${tarball}.sig`,certificate=`${tarball}.cert`;if(!deps.existsSync(signature))continue;if(!deps.existsSync(certificate))continue;let provenancePath=join79(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 dirname23(resolve17(options.tarball));return resolve17(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(join79(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,status=json2.verified?"OK":"FAIL";if(deps.stdout(`verify-install: ${status} (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",`
|
|
4382
4382
|
Examples:
|
|
4383
4383
|
# Quick triage of the current project and every home on the host.
|
|
4384
4384
|
$ genie sec scan --all-homes --root "$PWD"
|
|
@@ -4566,7 +4566,7 @@ ${mode}Closed ${result2.closed} task${result2.closed===1?"":"s"} from ${result2.
|
|
|
4566
4566
|
Name: ${t.name}`),console.log(`ID: ${t.id}`),console.log(`Builtin: ${t.isBuiltin}`),console.log(`Description: ${t.description??"(none)"}`),t.columns&&t.columns.length>0)console.log(`Columns: ${t.columns.map((c)=>c.name).join(", ")}`);console.log("")}),tmpl.command("delete <name>").description("Delete a template").action(async(name)=>{let{deleteTemplate:deleteTemplate2,getTemplate:getTemplate2}=await Promise.resolve().then(() => (init_template_service(),exports_template_service)),t=await getTemplate2(name);if(!t)console.error(`Template "${name}" not found.`),process.exit(1);let ok=await deleteTemplate2(t.id);console.log(ok?`Deleted template "${t.name}".`:"Delete failed.")})}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(`
|
|
4567
4567
|
${types4.length} type${types4.length===1?"":"s"}`)}function printTypePipeline(t){if(console.log(`
|
|
4568
4568
|
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(`
|
|
4569
|
-
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 existsSync67}from"fs";import{mkdir as mkdir12,readFile as readFile17,readdir as readdir11,stat as stat11,writeFile as writeFile11}from"fs/promises";import{dirname as
|
|
4569
|
+
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 existsSync67}from"fs";import{mkdir as mkdir12,readFile as readFile17,readdir as readdir11,stat as stat11,writeFile as writeFile11}from"fs/promises";import{dirname as dirname24,join as join81}from"path";function resolveTemplatePath(cwd=process.cwd()){let dir=cwd;for(let i2=0;i2<10;i2++){let candidate=join81(dir,"templates","wish-template.md");if(existsSync67(candidate))return candidate;let parent=dirname24(dir);if(parent===dir)break;dir=parent}return null}var FALLBACK_TEMPLATE=`# Wish: <TODO: title>
|
|
4570
4570
|
|
|
4571
4571
|
| Field | Value |
|
|
4572
4572
|
|-------|-------|
|
|
@@ -4638,5 +4638,5 @@ Examples:
|
|
|
4638
4638
|
genie spawn engineer # Spawn built-in engineer role
|
|
4639
4639
|
genie spawn researcher --model sonnet # Spawn with model override
|
|
4640
4640
|
genie spawn my-agent --team my-feature # Spawn into a specific team
|
|
4641
|
-
genie spawn council--questioner --provider codex # Use Codex provider`).action(async(name,options)=>{if(options.autoSync===!1)options.noAutoSync=!0;try{await handleWorkerSpawn(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.command("kill <name>").description("Force kill an agent by name").action(async(name)=>{try{await handleWorkerKill(name)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.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)}});program2.command("resume [name]").description("Resume a suspended/failed agent with its Claude session").option("--all","Resume all eligible agents").action(async(name,options)=>{try{await handleWorkerResume(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.command("history <name>").description("Show compressed session history for an agent").option("--full","Show full conversation without compression").option("--since <n>","Show last N user/assistant exchanges",Number.parseInt).option("--last <n>","Show last N transcript entries",Number.parseInt).option("--type <role>","Filter by role (user, assistant, tool_call)").option("--after <timestamp>","Only entries after ISO timestamp").option("--json","Output as JSON").option("--ndjson","Output as newline-delimited JSON (pipeable to jq)").option("--raw","Output raw JSONL entries").option("--log-file <path>","Direct path to log file (for testing)").action(async(name,options)=>{await historyCommand(name,options)});program2.command("log [agent]").description("Unified observability feed \u2014 aggregates transcript, DMs, team chat").option("--team <name>","Show interleaved feed for all agents in a team").option("--type <kind>","Filter by event kind (transcript, message, tool_call, state, system)").option("--since <timestamp>","Only events after ISO timestamp").option("--last <n>","Show last N events",Number.parseInt).option("--ndjson","Output as newline-delimited JSON (pipeable to jq)").option("--json","Output as pretty JSON").option("-f, --follow","Follow mode \u2014 real-time streaming").action(async(agent,options)=>{await logCommand(agent,options)});var qaCmd=program2.command("qa").description("QA \u2014 self-testing system for genie CLI");qaCmd.command("run [target]",{isDefault:!0}).description("Run QA specs (all, a domain, or a single spec)").option("--timeout <seconds>","Max seconds per spec",(v2)=>Number(v2),3600).option("--parallel <n>","Max specs to run in parallel",(v2)=>Number(v2),5).option("--verbose","Show all collected events").option("--ndjson","Machine-readable NDJSON output").action(async(target,options)=>{await qaCommand(target,options)});qaCmd.command("status").description("Show QA dashboard with last results per spec").option("--json","Output as JSON").action(async(options)=>{await qaStatusCommand(options)});qaCmd.command("history").description("Show recent QA runs").action(async()=>{await qaHistoryCommand()});qaCmd.command("check <specFile>").description("Evaluate a QA spec against current team logs and publish qa-report").option("--team <name>","Team name (defaults to GENIE_TEAM)").option("--since <timestamp>","Only consider events after this ISO timestamp").option("--since-file <path>","Read the lower-bound timestamp from a file").action(async(specFile,options)=>{await qaCheckCommand(specFile,options)});program2.command("qa-report <json>").description("Publish QA result to the PG event log (called by QA team-lead)").action(async(json2)=>{let team=process.env.GENIE_TEAM;if(!team)console.error("Error: GENIE_TEAM not set. This command must be run by a QA team-lead agent."),process.exit(1);try{let data=JSON.parse(json2),{publishSubjectEvent:publishSubjectEvent2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events));await publishSubjectEvent2(process.cwd(),`genie.qa.${team}.result`,{kind:"qa",agent:"qa",team,text:`QA result: ${String(data.result??"unknown")}`,data,source:"hook"}),console.log(`QA result published to PG event log as genie.qa.${team}.result`)}catch(err){console.error(`Failed to publish QA result: ${err}`),process.exit(1)}});program2.command("read <name>").description("Read terminal output from an agent pane").option("-n, --lines <number>","Number of lines to read").option("--from <line>","Start line").option("--to <line>","End line").option("--range <range>",'Line range (e.g., "10-20")').option("--search <text>","Search for text").option("--grep <pattern>","Grep for pattern").option("-f, --follow","Follow mode (like tail -f)").option("--all","Show all output").option("-r, --reverse","Reverse order").option("--json","Output as JSON").action(async(name,options)=>{await readSessionLogs2(name,options)});program2.command("answer <name> <choice>").description('Answer a question for an agent (use "text:..." for text input)').action(async(name,choice)=>{await answerQuestion(name,choice)});program2.command("status").description("Aggregated observability \u2014 agents to resume, active alerts, optional health checklist").option("--health","Add the four-item health checklist (partition, watchdog, spill, watcher metrics)").option("--all","Include archived / done agents").option("--debug","Add structural-inference audit (former `doctor --state`)").option("--json","Emit JSON instead of human output").action(async(options)=>{try{await statusCommand2(options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.command("ls").description("List registered agents with runtime status").option("--json","Output as JSON").option("--source <name>","Filter by executor metadata source (e.g. omni)").option("--all","Include archived agents (hidden by default)").action(async(options)=>{try{await handleLsCommand(options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});var args=process.argv.slice(2),isTuiPane=process.env.GENIE_TUI_PANE==="left"&&args.length===0,tuiRightPane=process.env.GENIE_TUI_RIGHT;delete process.env.GENIE_TUI_PANE;delete process.env.GENIE_TUI_RIGHT;delete process.env.GENIE_IS_DAEMON;if(isTuiPane){let{isTuiDisabled:isTuiDisabled2,noticeTuiSkipped:noticeTuiSkipped2}=await Promise.resolve().then(() => (init_tui_disable(),exports_tui_disable));if(isTuiDisabled2())noticeTuiSkipped2("renderer"),await new Promise(()=>{}),process.exit(0);if(tuiRightPane)process.env.GENIE_TUI_RIGHT=tuiRightPane;let{launchTui:launchTui2}=await Promise.resolve().then(() => (init_tui(),exports_tui));await launchTui2(),process.exit(0)}if(args.length===0){{let{isTuiDisabled:isTuiDisabled2,noticeTuiSkipped:noticeTuiSkipped2}=await Promise.resolve().then(() => (init_tui_disable(),exports_tui_disable));if(isTuiDisabled2())noticeTuiSkipped2("attach"),console.error(" Use `genie ls`, `genie spawn <agent>`, `genie log`, etc. directly."),console.error(" Unset GENIE_TUI_DISABLE (or omit --no-tui) to re-enable the TUI."),process.exit(0)}if(process.env.TMUX?.includes("genie-tui")){let{findWorkspace:findWorkspace3}=await Promise.resolve().then(() => (init_workspace(),exports_workspace)),ws2=findWorkspace3();if(ws2){let{resolveAgentFromCwd:resolveAgentFromCwd3}=await Promise.resolve().then(() => (init_resolve_agent_cwd(),exports_resolve_agent_cwd)),resolved2=resolveAgentFromCwd3(process.cwd(),ws2.root);if(resolved2.source!=="default"){let{writeFileSync:writeFileSync30}=await import("fs"),{join:join88}=await import("path"),home=process.env.GENIE_HOME??join88((await import("os")).homedir(),".genie");try{writeFileSync30(join88(home,"tui-initial-agent"),resolved2.agent,"utf-8")}catch{}console.log(`Navigating to ${resolved2.agent}...`)}else console.log("Already inside the genie TUI. Use Ctrl-b d to detach, or run genie commands directly.")}else console.log("Already inside the genie TUI. Use Ctrl-b d to detach, or run genie commands directly.");process.exit(0)}if(process.env.TMUX)console.warn("Note: switching to genie TUI from within another tmux session.");let{findWorkspace:findWorkspace2}=await Promise.resolve().then(() => (init_workspace(),exports_workspace)),ws=findWorkspace2();if(!ws){let{isInteractive:isInteractive2}=await Promise.resolve().then(() => (init_interactivity(),exports_interactivity));if(!isInteractive2())console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{confirm:confirm2}=await Promise.resolve().then(() => (init_esm14(),exports_esm));if(!await confirm2({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:mkdirSync30,writeFileSync:writeFileSync30}=await import("fs"),{basename:
|
|
4641
|
+
genie spawn council--questioner --provider codex # Use Codex provider`).action(async(name,options)=>{if(options.autoSync===!1)options.noAutoSync=!0;try{await handleWorkerSpawn(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.command("kill <name>").description("Force kill an agent by name").action(async(name)=>{try{await handleWorkerKill(name)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.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)}});program2.command("resume [name]").description("Resume a suspended/failed agent with its Claude session").option("--all","Resume all eligible agents").action(async(name,options)=>{try{await handleWorkerResume(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.command("history <name>").description("Show compressed session history for an agent").option("--full","Show full conversation without compression").option("--since <n>","Show last N user/assistant exchanges",Number.parseInt).option("--last <n>","Show last N transcript entries",Number.parseInt).option("--type <role>","Filter by role (user, assistant, tool_call)").option("--after <timestamp>","Only entries after ISO timestamp").option("--json","Output as JSON").option("--ndjson","Output as newline-delimited JSON (pipeable to jq)").option("--raw","Output raw JSONL entries").option("--log-file <path>","Direct path to log file (for testing)").action(async(name,options)=>{await historyCommand(name,options)});program2.command("log [agent]").description("Unified observability feed \u2014 aggregates transcript, DMs, team chat").option("--team <name>","Show interleaved feed for all agents in a team").option("--type <kind>","Filter by event kind (transcript, message, tool_call, state, system)").option("--since <timestamp>","Only events after ISO timestamp").option("--last <n>","Show last N events",Number.parseInt).option("--ndjson","Output as newline-delimited JSON (pipeable to jq)").option("--json","Output as pretty JSON").option("-f, --follow","Follow mode \u2014 real-time streaming").action(async(agent,options)=>{await logCommand(agent,options)});var qaCmd=program2.command("qa").description("QA \u2014 self-testing system for genie CLI");qaCmd.command("run [target]",{isDefault:!0}).description("Run QA specs (all, a domain, or a single spec)").option("--timeout <seconds>","Max seconds per spec",(v2)=>Number(v2),3600).option("--parallel <n>","Max specs to run in parallel",(v2)=>Number(v2),5).option("--verbose","Show all collected events").option("--ndjson","Machine-readable NDJSON output").action(async(target,options)=>{await qaCommand(target,options)});qaCmd.command("status").description("Show QA dashboard with last results per spec").option("--json","Output as JSON").action(async(options)=>{await qaStatusCommand(options)});qaCmd.command("history").description("Show recent QA runs").action(async()=>{await qaHistoryCommand()});qaCmd.command("check <specFile>").description("Evaluate a QA spec against current team logs and publish qa-report").option("--team <name>","Team name (defaults to GENIE_TEAM)").option("--since <timestamp>","Only consider events after this ISO timestamp").option("--since-file <path>","Read the lower-bound timestamp from a file").action(async(specFile,options)=>{await qaCheckCommand(specFile,options)});program2.command("qa-report <json>").description("Publish QA result to the PG event log (called by QA team-lead)").action(async(json2)=>{let team=process.env.GENIE_TEAM;if(!team)console.error("Error: GENIE_TEAM not set. This command must be run by a QA team-lead agent."),process.exit(1);try{let data=JSON.parse(json2),{publishSubjectEvent:publishSubjectEvent2}=await Promise.resolve().then(() => (init_runtime_events(),exports_runtime_events));await publishSubjectEvent2(process.cwd(),`genie.qa.${team}.result`,{kind:"qa",agent:"qa",team,text:`QA result: ${String(data.result??"unknown")}`,data,source:"hook"}),console.log(`QA result published to PG event log as genie.qa.${team}.result`)}catch(err){console.error(`Failed to publish QA result: ${err}`),process.exit(1)}});program2.command("read <name>").description("Read terminal output from an agent pane").option("-n, --lines <number>","Number of lines to read").option("--from <line>","Start line").option("--to <line>","End line").option("--range <range>",'Line range (e.g., "10-20")').option("--search <text>","Search for text").option("--grep <pattern>","Grep for pattern").option("-f, --follow","Follow mode (like tail -f)").option("--all","Show all output").option("-r, --reverse","Reverse order").option("--json","Output as JSON").action(async(name,options)=>{await readSessionLogs2(name,options)});program2.command("answer <name> <choice>").description('Answer a question for an agent (use "text:..." for text input)').action(async(name,choice)=>{await answerQuestion(name,choice)});program2.command("status").description("Aggregated observability \u2014 agents to resume, active alerts, optional health checklist").option("--health","Add the four-item health checklist (partition, watchdog, spill, watcher metrics)").option("--all","Include archived / done agents").option("--debug","Add structural-inference audit (former `doctor --state`)").option("--json","Emit JSON instead of human output").action(async(options)=>{try{await statusCommand2(options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});program2.command("ls").description("List registered agents with runtime status").option("--json","Output as JSON").option("--source <name>","Filter by executor metadata source (e.g. omni)").option("--all","Include archived agents (hidden by default)").action(async(options)=>{try{await handleLsCommand(options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});var args=process.argv.slice(2),isTuiPane=process.env.GENIE_TUI_PANE==="left"&&args.length===0,tuiRightPane=process.env.GENIE_TUI_RIGHT;delete process.env.GENIE_TUI_PANE;delete process.env.GENIE_TUI_RIGHT;delete process.env.GENIE_IS_DAEMON;if(isTuiPane){let{isTuiDisabled:isTuiDisabled2,noticeTuiSkipped:noticeTuiSkipped2}=await Promise.resolve().then(() => (init_tui_disable(),exports_tui_disable));if(isTuiDisabled2())noticeTuiSkipped2("renderer"),await new Promise(()=>{}),process.exit(0);if(tuiRightPane)process.env.GENIE_TUI_RIGHT=tuiRightPane;let{launchTui:launchTui2}=await Promise.resolve().then(() => (init_tui(),exports_tui));await launchTui2(),process.exit(0)}if(args.length===0){{let{isTuiDisabled:isTuiDisabled2,noticeTuiSkipped:noticeTuiSkipped2}=await Promise.resolve().then(() => (init_tui_disable(),exports_tui_disable));if(isTuiDisabled2())noticeTuiSkipped2("attach"),console.error(" Use `genie ls`, `genie spawn <agent>`, `genie log`, etc. directly."),console.error(" Unset GENIE_TUI_DISABLE (or omit --no-tui) to re-enable the TUI."),process.exit(0)}if(process.env.TMUX?.includes("genie-tui")){let{findWorkspace:findWorkspace3}=await Promise.resolve().then(() => (init_workspace(),exports_workspace)),ws2=findWorkspace3();if(ws2){let{resolveAgentFromCwd:resolveAgentFromCwd3}=await Promise.resolve().then(() => (init_resolve_agent_cwd(),exports_resolve_agent_cwd)),resolved2=resolveAgentFromCwd3(process.cwd(),ws2.root);if(resolved2.source!=="default"){let{writeFileSync:writeFileSync30}=await import("fs"),{join:join88}=await import("path"),home=process.env.GENIE_HOME??join88((await import("os")).homedir(),".genie");try{writeFileSync30(join88(home,"tui-initial-agent"),resolved2.agent,"utf-8")}catch{}console.log(`Navigating to ${resolved2.agent}...`)}else console.log("Already inside the genie TUI. Use Ctrl-b d to detach, or run genie commands directly.")}else console.log("Already inside the genie TUI. Use Ctrl-b d to detach, or run genie commands directly.");process.exit(0)}if(process.env.TMUX)console.warn("Note: switching to genie TUI from within another tmux session.");let{findWorkspace:findWorkspace2}=await Promise.resolve().then(() => (init_workspace(),exports_workspace)),ws=findWorkspace2();if(!ws){let{isInteractive:isInteractive2}=await Promise.resolve().then(() => (init_interactivity(),exports_interactivity));if(!isInteractive2())console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{confirm:confirm2}=await Promise.resolve().then(() => (init_esm14(),exports_esm));if(!await confirm2({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:mkdirSync30,writeFileSync:writeFileSync30}=await import("fs"),{basename:basename18,join:join88}=await import("path"),cwd=process.cwd(),genieDir=join88(cwd,".genie");mkdirSync30(genieDir,{recursive:!0});let config={name:basename18(cwd),agents:{defaults:{}},tmux:{socket:"genie"},sdk:{}};if(writeFileSync30(join88(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
|
|
4642
4642
|
`),console.log(`Workspace initialized: ${cwd}`),ws=findWorkspace2(),!ws)console.error("Failed to initialize workspace."),process.exit(1)}let{resolveAgentFromCwd:resolveAgentFromCwd2}=await Promise.resolve().then(() => (init_resolve_agent_cwd(),exports_resolve_agent_cwd)),resolved=resolveAgentFromCwd2(process.cwd(),ws.root),initialAgent=resolved.agent,{isServeRunning:isServeRunning2,autoStartServe:autoStartServe2,isTuiSessionReady:isTuiSessionReady2,ensureTuiSession:ensureTuiSession2}=await Promise.resolve().then(() => (init_serve(),exports_serve));if(!isServeRunning2())console.log("Starting genie serve..."),await autoStartServe2();else if(!isTuiSessionReady2())ensureTuiSession2(ws.root);if(ws.root)process.env.GENIE_TUI_WORKSPACE=ws.root;if(initialAgent)process.env.GENIE_TUI_AGENT=initialAgent;if(resolved.source!=="default"){let{execSync:execSync19}=await import("child_process");try{execSync19(`tmux has-session -t =${initialAgent} 2>/dev/null`,{stdio:"pipe"})}catch{console.log(`Spawning ${initialAgent}...`);try{execSync19(`genie spawn ${initialAgent}`,{stdio:"inherit",timeout:15000})}catch{}}}if(initialAgent){let{writeFileSync:writeFileSync30}=await import("fs"),{join:join88}=await import("path"),home=process.env.GENIE_HOME??join88((await import("os")).homedir(),".genie");try{writeFileSync30(join88(home,"tui-initial-agent"),initialAgent,"utf-8")}catch{}}let{attachTuiSession:attachTuiSession2}=await Promise.resolve().then(() => (init_tmux2(),exports_tmux2));attachTuiSession2(),process.exit(0)}if(args.every((a)=>a==="--reset")){let{sessionCommand:sessionCommand2}=await Promise.resolve().then(() => (init_session(),exports_session));await sessionCommand2({reset:!0}),process.exit(0)}var sessionIdx=args.indexOf("--session");if(sessionIdx!==-1&&sessionIdx+1<args.length){let sessionName=args[sessionIdx+1];if(!args.filter((_2,i2)=>i2!==sessionIdx&&i2!==sessionIdx+1).some((a)=>!a.startsWith("-")))try{await startNamedSession(sessionName),process.exit(0)}catch(err){console.error(`Error: ${err instanceof Error?err.message:err}`),process.exit(1)}else try{await program2.parseAsync(process.argv)}finally{await stopOtelReceiver().catch(()=>{}),await shutdown().catch(()=>{})}}else try{let _cmdStart=Date.now();if(await program2.parseAsync(process.argv),process.env.GENIE_PROFILE_DB)console.error(`[profile] parseAsync=${Date.now()-_cmdStart}ms`)}finally{let _shutStart=Date.now();if(await stopOtelReceiver().catch(()=>{}),await shutdown().catch(()=>{}),process.env.GENIE_PROFILE_DB)console.error(`[profile] shutdown=${Date.now()-_shutStart}ms`)}
|