@automagik/genie 4.260505.4 → 4.260506.1
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
|
@@ -624,7 +624,8 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
|
|
|
624
624
|
)
|
|
625
625
|
`)}async function recordMigrationComplete(target,sourceDb,rowsCopied){await ensureMigrationStateTable(target),await target.unsafe(`INSERT INTO _genie_migration_state (source_db, rows_copied)
|
|
626
626
|
VALUES ($1, $2::jsonb)
|
|
627
|
-
ON CONFLICT (source_db) DO UPDATE SET completed_at = now(), rows_copied = EXCLUDED.rows_copied`,[sourceDb,JSON.stringify(rowsCopied)])}var V1_DB_NAME="genie",PG_USER="postgres",PG_PASS="postgres",PG_HOST="127.0.0.1",promptedThisProcess=!1;var init_v1_migration_prompt=__esm(()=>{init_src()});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,requirePgserveDaemon:()=>requirePgserveDaemon,readPostmasterDiscovery:()=>readPostmasterDiscovery,probePgserveDaemon:()=>probePgserveDaemon,pinCwdToGeniePackageDir:()=>pinCwdToGeniePackageDir,isSocketMode:()=>isSocketMode,isConnected:()=>isConnected,isAvailable:()=>isAvailable,getLockfilePath:()=>getLockfilePath,getDataDir:()=>getDataDir,getConnection:()=>getConnection,getAuxiliaryPortBase:()=>getAuxiliaryPortBase,getActivePort:()=>getActivePort,ensurePgserve:()=>ensurePgserve,checkRootGuard:()=>checkRootGuard,autoStartDaemon:()=>autoStartDaemon,__setSpawnDaemonForTest:()=>__setSpawnDaemonForTest,DB_NAME:()=>DB_NAME});import{spawn}from"child_process";import{existsSync as existsSync11,mkdirSync as mkdirSync5,readFileSync as readFileSync7,renameSync,unlinkSync as unlinkSync3,writeFileSync as writeFileSync4}from"fs";import{createConnection}from"net";import{homedir as homedir10}from"os";import{dirname as dirname3,join as join14}from"path";function resolvePgserveSocketDir(){let xdg=process.env.XDG_RUNTIME_DIR,base=xdg&&xdg.length>0?xdg:"/tmp";return join14(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 join14(resolvePgserveSocketDir(),".s.PGSQL.5432")}function resolvePgserveControlSocketPath(){return join14(resolvePgserveSocketDir(),"control.sock")}function resolvePgserveDaemonPidPath(){return join14(resolvePgserveSocketDir(),"pgserve.pid")}function readPostmasterDiscovery(){let file=join14(resolvePgserveSocketDir(),"admin.json");if(!existsSync11(file))return null;let raw;try{raw=readFileSync7(file,"utf-8")}catch{return null}let parsed;try{parsed=JSON.parse(raw)}catch{return null}if(!parsed||typeof parsed!=="object")return null;let obj=parsed,socketDir=typeof obj.socketDir==="string"&&obj.socketDir.length>0?obj.socketDir:null,port=typeof obj.port==="number"&&Number.isFinite(obj.port)&&obj.port>0?obj.port:null,pid=typeof obj.pid==="number"&&Number.isFinite(obj.pid)&&obj.pid>0?obj.pid:null;if(!socketDir||!port)return null;if(!existsSync11(join14(socketDir,`.s.PGSQL.${port}`)))return null;return{socketDir,port,pid:pid??-1}}function probePgserveDaemon(){let socketPresent=existsSync11(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(!existsSync11(pidPath))return null;try{let raw=readFileSync7(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 resolveGeniePackageDir(){if(geniePackageDirCache!==void 0)return geniePackageDirCache;let PACKAGE_NAME="@automagik/genie",MAX_WALK_DEPTH=10,current=dirname3(import.meta.dir??__dirname);for(let depth=0;depth<MAX_WALK_DEPTH;depth++){let candidate=join14(current,"package.json");try{if(existsSync11(candidate)){if(JSON.parse(readFileSync7(candidate,"utf-8"))?.name===PACKAGE_NAME)return geniePackageDirCache=current,current}}catch{}let parent=dirname3(current);if(parent===current)break;current=parent}return geniePackageDirCache=null,null}function pinCwdToGeniePackageDir(){let previous=process.cwd();if(daemonCwdPinned)return{previous,pinned:previous};let dir=resolveGeniePackageDir();if(!dir)return{previous,pinned:null};try{if(process.cwd()!==dir)process.chdir(dir);return daemonCwdPinned=!0,{previous,pinned:dir}}catch{return{previous,pinned:null}}}async function requirePgserveDaemon(){let state=probePgserveDaemon();if(state.running&&await isPgserveSocketResponsive())return state;if(state.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"};throw Error(buildPgserveUnavailableHint(state))}function buildPgserveUnavailableHint(state){return[`pgserve canonical daemon is not reachable (${state.reason??"no daemon"}).`,"Genie depends on the pm2-supervised pgserve singleton. Recovery:"," pm2 status # is pgserve registered?"," pm2 restart pgserve # OR: autopg restart"," pgserve install # if not registered yet","See https://github.com/automagik-dev/genie/blob/main/docs/install.md for details."].join(`
|
|
627
|
+
ON CONFLICT (source_db) DO UPDATE SET completed_at = now(), rows_copied = EXCLUDED.rows_copied`,[sourceDb,JSON.stringify(rowsCopied)])}var V1_DB_NAME="genie",PG_USER="postgres",PG_PASS="postgres",PG_HOST="127.0.0.1",promptedThisProcess=!1;var init_v1_migration_prompt=__esm(()=>{init_src()});var exports_db={};__export(exports_db,{shutdown:()=>shutdown,runRetention:()=>runRetention,resolveTcpPgPassword:()=>resolveTcpPgPassword,resolvePgserveTransport:()=>resolvePgserveTransport,resolvePgserveSocketDir:()=>resolvePgserveSocketDir,resolvePgserveLibpqSocketPath:()=>resolvePgserveLibpqSocketPath,resolvePgserveDaemonPidPath:()=>resolvePgserveDaemonPidPath,resolvePgserveControlSocketPath:()=>resolvePgserveControlSocketPath,resolvePgserveAuthPassword:()=>resolvePgserveAuthPassword,resolveDatabaseName:()=>resolveDatabaseName,resetConnection:()=>resetConnection,requirePgserveDaemon:()=>requirePgserveDaemon,readPostmasterDiscovery:()=>readPostmasterDiscovery,probePgserveDaemon:()=>probePgserveDaemon,pinCwdToGeniePackageDir:()=>pinCwdToGeniePackageDir,isSocketMode:()=>isSocketMode,isConnected:()=>isConnected,isAvailable:()=>isAvailable,getLockfilePath:()=>getLockfilePath,getDataDir:()=>getDataDir,getConnection:()=>getConnection,getAuxiliaryPortBase:()=>getAuxiliaryPortBase,getActivePort:()=>getActivePort,ensurePgserve:()=>ensurePgserve,checkRootGuard:()=>checkRootGuard,autoStartDaemon:()=>autoStartDaemon,__setSpawnDaemonForTest:()=>__setSpawnDaemonForTest,DB_NAME:()=>DB_NAME});import{spawn}from"child_process";import{existsSync as existsSync11,mkdirSync as mkdirSync5,readFileSync as readFileSync7,renameSync,unlinkSync as unlinkSync3,writeFileSync as writeFileSync4}from"fs";import{createConnection}from"net";import{homedir as homedir10}from"os";import{dirname as dirname3,join as join14}from"path";function resolvePgserveSocketDir(){let xdg=process.env.XDG_RUNTIME_DIR,base=xdg&&xdg.length>0?xdg:"/tmp";return join14(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 join14(resolvePgserveSocketDir(),".s.PGSQL.5432")}function resolvePgserveControlSocketPath(){return join14(resolvePgserveSocketDir(),"control.sock")}function resolvePgserveDaemonPidPath(){return join14(resolvePgserveSocketDir(),"pgserve.pid")}function readPostmasterDiscovery(){let file=join14(resolvePgserveSocketDir(),"admin.json");if(!existsSync11(file))return null;let raw;try{raw=readFileSync7(file,"utf-8")}catch{return null}let parsed;try{parsed=JSON.parse(raw)}catch{return null}if(!parsed||typeof parsed!=="object")return null;let obj=parsed,socketDir=typeof obj.socketDir==="string"&&obj.socketDir.length>0?obj.socketDir:null,port=typeof obj.port==="number"&&Number.isFinite(obj.port)&&obj.port>0?obj.port:null,pid=typeof obj.pid==="number"&&Number.isFinite(obj.pid)&&obj.pid>0?obj.pid:null;if(!socketDir||!port)return null;if(!existsSync11(join14(socketDir,`.s.PGSQL.${port}`)))return null;return{socketDir,port,pid:pid??-1}}function probePgserveDaemon(){let socketPresent=existsSync11(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(!existsSync11(pidPath))return null;try{let raw=readFileSync7(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 resolveGeniePackageDir(){if(geniePackageDirCache!==void 0)return geniePackageDirCache;let PACKAGE_NAME="@automagik/genie",MAX_WALK_DEPTH=10,current=dirname3(import.meta.dir??__dirname);for(let depth=0;depth<MAX_WALK_DEPTH;depth++){let candidate=join14(current,"package.json");try{if(existsSync11(candidate)){if(JSON.parse(readFileSync7(candidate,"utf-8"))?.name===PACKAGE_NAME)return geniePackageDirCache=current,current}}catch{}let parent=dirname3(current);if(parent===current)break;current=parent}return geniePackageDirCache=null,null}function pinCwdToGeniePackageDir(){let previous=process.cwd();if(daemonCwdPinned)return{previous,pinned:previous};let dir=resolveGeniePackageDir();if(!dir)return{previous,pinned:null};try{if(process.cwd()!==dir)process.chdir(dir);return daemonCwdPinned=!0,{previous,pinned:dir}}catch{return{previous,pinned:null}}}async function requirePgserveDaemon(){let state=probePgserveDaemon();if(state.running&&await isPgserveSocketResponsive())return state;if(state.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"};throw Error(buildPgserveUnavailableHint(state))}function buildPgserveUnavailableHint(state){return[`pgserve canonical daemon is not reachable (${state.reason??"no daemon"}).`,"Genie depends on the pm2-supervised pgserve singleton. Recovery:"," pm2 status # is pgserve registered?"," pm2 restart pgserve # OR: autopg restart"," pgserve install # if not registered yet","See https://github.com/automagik-dev/genie/blob/main/docs/install.md for details."].join(`
|
|
628
|
+
`)}async function resolvePgserveTransport(){let forceTcp=process.env.GENIE_PG_FORCE_TCP==="1",forceSocket=process.env.GENIE_PG_FORCE_SOCKET==="1";if(!forceTcp){let udsState=probePgserveDaemon();if(udsState.running&&await isPgserveSocketResponsive()){let discovery=readPostmasterDiscovery();return{kind:"unix",socketDir:discovery?.socketDir??resolvePgserveSocketDir(),port:discovery?.port??5432}}if(udsState.reason==="socket present but pid stale"&&await isPgserveSocketResponsive())return{kind:"unix",socketDir:resolvePgserveSocketDir(),port:5432};if(forceSocket)throw Error(buildPgserveUnavailableHint(udsState))}let explicitPort=parseExplicitTcpPort(process.env.GENIE_PG_PORT);if(explicitPort!==null)return{kind:"tcp",host:DEFAULT_HOST,port:explicitPort};let tcpPort=await discoverTcpPgservePort();if(tcpPort!==null)return{kind:"tcp",host:DEFAULT_HOST,port:tcpPort};throw Error(buildBothTransportsUnavailableHint(forceTcp,forceSocket))}function parseExplicitTcpPort(raw){if(raw===void 0||raw==="")return null;let parsed=Number.parseInt(raw.trim(),10);if(!Number.isFinite(parsed)||parsed<=0||parsed>65535)return null;return parsed}async function discoverTcpPgservePort(){return new Promise((resolve2)=>{let settled=!1,stdout="",proc=spawn("pgserve",["port"],{stdio:["ignore","pipe","ignore"]}),timer2=setTimeout(()=>{if(settled)return;settled=!0,proc.kill("SIGTERM"),resolve2(null)},TCP_DISCOVERY_TIMEOUT_MS);timer2.unref(),proc.stdout?.setEncoding("utf8"),proc.stdout?.on("data",(chunk)=>{stdout+=chunk}),proc.on("error",()=>{if(settled)return;settled=!0,clearTimeout(timer2),resolve2(null)}),proc.on("close",(code)=>{if(settled)return;if(settled=!0,clearTimeout(timer2),code!==0){resolve2(null);return}let parsed=Number.parseInt(stdout.trim(),10);if(!Number.isFinite(parsed)||parsed<=0||parsed>65535){resolve2(null);return}resolve2(parsed)})})}function buildBothTransportsUnavailableHint(forceTcp,forceSocket){let lines=["pgserve is not reachable on either transport."];if(!forceTcp)lines.push(` \u2022 Unix socket probe: ${resolvePgserveLibpqSocketPath()} (not present or not responsive)`);else lines.push(" \u2022 Unix socket probe: skipped (GENIE_PG_FORCE_TCP=1)");if(!forceSocket)lines.push(" \u2022 TCP discovery via `pgserve port`: failed (binary missing or no daemon)");else lines.push(" \u2022 TCP discovery: skipped (GENIE_PG_FORCE_SOCKET=1)");return lines.push("Recovery:"),lines.push(" pm2 status # is pgserve registered?"),lines.push(" pgserve install # register foreground TCP-mode pgserve under pm2"),lines.push(" pgserve daemon # OR start daemon-mode (canonical UDS) standalone"),lines.push("See https://github.com/automagik-dev/genie/blob/main/docs/install.md for details."),lines.join(`
|
|
628
629
|
`)}async function isPgserveSocketResponsive(){let candidates=[resolvePgserveLibpqSocketPath(),resolvePgserveControlSocketPath()].filter((path2)=>existsSync11(path2));for(let path2 of candidates)if(await canCompletePgserveGreet(path2))return!0;return!1}function canCompletePgserveGreet(path2){return new Promise((resolve2)=>{let settled=!1,timer2=null,socket=null,finish=(ok)=>{if(settled)return;if(settled=!0,timer2)clearTimeout(timer2);socket?.removeAllListeners(),socket?.destroy(),resolve2(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 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 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((resolve2)=>{setTimeout(()=>resolve2(!1),4000).unref()})])}catch{return!1}}function readLockfile(){try{let content=readFileSync7(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{mkdirSync5(GENIE_HOME,{recursive:!0});let tmpPath=`${LOCKFILE_PATH}.tmp.${process.pid}`;writeFileSync4(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(`
|
|
629
630
|
DELETE FROM heartbeats WHERE created_at < now() - interval '7 days';
|
|
630
631
|
DELETE FROM machine_snapshots WHERE created_at < now() - interval '30 days';
|
|
@@ -632,11 +633,11 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
|
|
|
632
633
|
DELETE FROM genie_runtime_events WHERE created_at < now() - interval '14 days';
|
|
633
634
|
`),retentionRan=!0}catch(retErr){retentionRan=!0;let msg=retErr instanceof Error?retErr.message:String(retErr);process.stderr.write(`[genie] retention cleanup warning: ${msg}
|
|
634
635
|
`)}}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 readFileSync7(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=join14(home,"serve.pid"),raw=readPidFile(pidPath);if(!raw){spawnDaemon();return}let parsed=parsePidFile(raw);if(!parsed){unlinkQuiet(pidPath),spawnDaemon();return}if(isServeAlive(parsed.pid,parsed.recordedStartTime))return;unlinkQuiet(pidPath),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 _ensurePgserve(){if(activePort!==null)return activePort;let port=getPort(),existing=await tryExistingPort(port);if(existing!==null)return existing;throw process.env.GENIE_PG_AVAILABLE="false",Error([`pgserve TCP port ${port} is not reachable.`,"Genie is consumer-only after the canonical-pgserve cutover; it does not spawn pgserve.","Force-TCP mode (GENIE_PG_FORCE_TCP=1) requires you to start a TCP-listening pgserve yourself.","Recommended: drop GENIE_PG_FORCE_TCP and let genie connect via the canonical Unix socket:"," pm2 status # is pgserve registered?"," pm2 restart pgserve # OR: autopg restart"," pgserve install # if not registered yet"].join(`
|
|
635
|
-
`))}function registerExitHandler(){if(exitHandlerRegistered)return;exitHandlerRegistered=!0;let cleanup=()=>{if(sqlClient){let dying=sqlClient;sqlClient=null,dying.end({timeout:1}).catch(()=>{})}if(ownsLockfile)removeLockfile(),ownsLockfile=!1};process.on("exit",cleanup),process.on("beforeExit",()=>{shutdown().catch(()=>{})})}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);if(!skipBoot)await maybePromptV1Migration(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}}
|
|
636
|
-
`)}catch{}bannerPrinted=!0}async function _buildConnection(){let _t0=Date.now()
|
|
636
|
+
`))}function registerExitHandler(){if(exitHandlerRegistered)return;exitHandlerRegistered=!0;let cleanup=()=>{if(sqlClient){let dying=sqlClient;sqlClient=null,dying.end({timeout:1}).catch(()=>{})}if(ownsLockfile)removeLockfile(),ownsLockfile=!1};process.on("exit",cleanup),process.on("beforeExit",()=>{shutdown().catch(()=>{})})}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);if(!skipBoot)await maybePromptV1Migration(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}}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}
|
|
637
|
+
`)}catch{}bannerPrinted=!0}async function _buildConnection(){let _t0=Date.now();if(Boolean(process.env.GENIE_TEST_PG_PORT)){let transport2=await resolveTransport(!1);return await buildAndOpenConnection(transport2,_t0)}let probed=await resolvePgserveTransport(),transport={useSocket:probed.kind==="unix",host:probed.kind==="unix"?probed.socketDir:probed.host,port:probed.port,pgWireCredential:probed.kind==="unix"?resolvePgserveAuthPassword():resolveTcpPgPassword()};return await buildAndOpenConnection(transport,_t0)}async function buildAndOpenConnection(transport,_t0){let useSocket=transport.useSocket,_t1=Date.now(),pgModule=(await Promise.resolve().then(() => (init_src(),exports_src))).default,database=resolveDatabaseName(),isTestMode=Boolean(process.env.GENIE_TEST_DB_NAME),cliShortLived=!daemonCwdPinned&&!isTestMode&&process.env.GENIE_SKIP_DB_BOOT==="1",shouldRestoreCwd=!daemonCwdPinned&&!isTestMode,cwdPin=pinCwdForFingerprint(),client=pgModule(buildPgClientOptions(transport,database,cliShortLived));sqlClient=client;try{if(await client`SELECT 1`,registerExitHandler(),await runPostConnectSetup(client,isTestMode,{t0:_t0,t1:_t1}),await maybePrintBanner(client,isTestMode),useSocket)activePort=SOCKET_PORT_SENTINEL;else activePort=transport.port;process.env.GENIE_PG_AVAILABLE="true"}catch(err){if(sqlClient===client)sqlClient=null;throw activePort=null,client.end({timeout:2}).catch(()=>{}),err}finally{restoreCwdAfterFingerprint(cwdPin,shouldRestoreCwd)}return client}async function resolveTransport(useSocket){let discovery=useSocket?readPostmasterDiscovery():null,port=useSocket?discovery?.port??5432:await ensurePgserve(),host=useSocket?discovery?.socketDir??resolvePgserveSocketDir():DEFAULT_HOST,pgWireCredential=useSocket?resolvePgserveAuthPassword():resolveTcpPgPassword();return{useSocket,host,port,pgWireCredential}}function pinCwdForFingerprint(){let originalCwd=process.cwd(),pkgDir=resolveGeniePackageDir();if(!pkgDir)return process.stderr.write(`[pgserve] WARN: could not resolve genie package dir; pgserve fingerprint may be unstable
|
|
637
638
|
`),{originalCwd,pinned:!1};if(process.cwd()===pkgDir)return{originalCwd,pinned:!1};try{return process.chdir(pkgDir),{originalCwd,pinned:!0}}catch(err){let msg=err instanceof Error?err.message:String(err);return process.stderr.write(`[pgserve] WARN: failed to pin cwd to ${pkgDir}: ${msg}
|
|
638
639
|
`),{originalCwd,pinned:!1}}}function restoreCwdAfterFingerprint(cwdPin,shouldRestoreCwd){if(!cwdPin.pinned||!shouldRestoreCwd||process.cwd()===cwdPin.originalCwd)return;try{process.chdir(cwdPin.originalCwd)}catch(err){let msg=err instanceof Error?err.message:String(err);process.stderr.write(`[pgserve] WARN: failed to restore cwd to ${cwdPin.originalCwd}: ${msg}
|
|
639
|
-
`)}}function buildPgClientOptions(transport,database,cliShortLived){return{host:transport.host,port:transport.port,database,username:DB_NAME,[PG_AUTH_FIELD]:transport.pgWireCredential,max:cliShortLived?1:50,idle_timeout:cliShortLived?0:1,connect_timeout:resolvePgConnectTimeoutSeconds(transport.useSocket),onnotice:()=>{},connection:{client_min_messages:"warning"}}}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 getAuxiliaryPortBase(){return activePort===SOCKET_PORT_SENTINEL?getPort():getActivePort()}function isSocketMode(){return activePort===SOCKET_PORT_SENTINEL}function getLockfilePath(){return LOCKFILE_PATH}var __dirname="/home/runner/_work/genie/genie/src/lib",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,sqlClient=null,activePort=null,ensurePromise=null,geniePackageDirCache=void 0,daemonCwdPinned=!1,buildPromise=null,ownsLockfile=!1,exitHandlerRegistered=!1,retentionRan=!1,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();init_v1_migration_prompt();GENIE_HOME=process.env.GENIE_HOME??join14(homedir10(),".genie"),DATA_DIR=join14(GENIE_HOME,"data","pgserve"),LOCKFILE_PATH=join14(GENIE_HOME,"pgserve.port"),PG_AUTH_FIELD=["pass","word"].join(""),DB_NAME=["post","gres"].join("")});var{$:$2}=globalThis.Bun;async function checkCommand(cmd){try{let cmdPath=(await $2`which ${cmd}`.quiet().text()).trim();if(!cmdPath)return{exists:!1};let version;try{let firstLine=(await $2`${cmd} --version`.quiet().text()).split(`
|
|
640
|
+
`)}}function buildPgClientOptions(transport,database,cliShortLived){return{host:transport.host,port:transport.port,database,username:DB_NAME,[PG_AUTH_FIELD]:transport.pgWireCredential,max:cliShortLived?1:50,idle_timeout:cliShortLived?0:1,connect_timeout:resolvePgConnectTimeoutSeconds(transport.useSocket),onnotice:()=>{},connection:{client_min_messages:"warning"}}}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 getAuxiliaryPortBase(){return activePort===SOCKET_PORT_SENTINEL?getPort():getActivePort()}function isSocketMode(){return activePort===SOCKET_PORT_SENTINEL}function getLockfilePath(){return LOCKFILE_PATH}var __dirname="/home/runner/_work/genie/genie/src/lib",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,TCP_DISCOVERY_TIMEOUT_MS=5000,sqlClient=null,activePort=null,ensurePromise=null,geniePackageDirCache=void 0,daemonCwdPinned=!1,buildPromise=null,ownsLockfile=!1,exitHandlerRegistered=!1,retentionRan=!1,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();init_v1_migration_prompt();GENIE_HOME=process.env.GENIE_HOME??join14(homedir10(),".genie"),DATA_DIR=join14(GENIE_HOME,"data","pgserve"),LOCKFILE_PATH=join14(GENIE_HOME,"pgserve.port"),PG_AUTH_FIELD=["pass","word"].join(""),DB_NAME=["post","gres"].join("")});var{$:$2}=globalThis.Bun;async function checkCommand(cmd){try{let cmdPath=(await $2`which ${cmd}`.quiet().text()).trim();if(!cmdPath)return{exists:!1};let version;try{let firstLine=(await $2`${cmd} --version`.quiet().text()).split(`
|
|
640
641
|
`)[0].trim(),versionMatch=firstLine.match(/(\d+\.[\d.]+[a-z0-9-]*)/i);version=versionMatch?versionMatch[1]:firstLine.slice(0,50)}catch{try{let firstLine=(await $2`${cmd} -v`.quiet().text()).split(`
|
|
641
642
|
`)[0].trim(),versionMatch=firstLine.match(/(\d+\.[\d.]+[a-z0-9-]*)/i);version=versionMatch?versionMatch[1]:firstLine.slice(0,50)}catch{}}return{exists:!0,version,path:cmdPath}}catch{return{exists:!1}}}var init_system_detect=()=>{};var exports_workspace={};__export(exports_workspace,{validateWorkspaceDefaults:()=>validateWorkspaceDefaults,scanAgents:()=>scanAgents2,migrateWorkspaceConfig:()=>migrateWorkspaceConfig,getWorkspaceConfig:()=>getWorkspaceConfig,genieHome:()=>genieHome2,findWorkspace:()=>findWorkspace,AgentDefaultsSchema:()=>AgentDefaultsSchema});import{existsSync as existsSync12,mkdirSync as mkdirSync6,readFileSync as readFileSync8,readdirSync as readdirSync4,realpathSync as realpathSync2,writeFileSync as writeFileSync5}from"fs";import{homedir as homedir11,tmpdir as tmpdir2}from"os";import{dirname as dirname4,join as join15,resolve as resolve2,sep}from"path";function findWorkspace(cwd,opts){let startDir=resolve2(cwd??process.cwd()),current=startDir,userHome=opts?.userHome??homedir11();while(!0){if(current!==userHome){let candidate=join15(current,WORKSPACE_MARKER);if(existsSync12(candidate)){saveWorkspaceRoot(current);let agent=detectAgent(startDir,current);return{root:current,agent:agent??void 0}}}let parent=dirname4(current);if(parent===current)break;current=parent}let savedRoot=loadWorkspaceRoot();if(savedRoot&&savedRoot!==userHome&&existsSync12(join15(savedRoot,WORKSPACE_MARKER))){let agent=detectAgent(startDir,savedRoot);return{root:savedRoot,agent:agent??void 0}}return null}function genieHome2(){return process.env.GENIE_HOME??join15(homedir11(),".genie")}function isTempPath(root){try{let canonicalTmp=realpathSync2(tmpdir2()),canonicalRoot=realpathSync2(root);return canonicalRoot===canonicalTmp||canonicalRoot.startsWith(canonicalTmp+sep)}catch{return!0}}function saveWorkspaceRoot(root){if(isTempPath(root))return;try{let home=genieHome2(),configPath2=join15(home,"config.json"),config=existsSync12(configPath2)?JSON.parse(readFileSync8(configPath2,"utf-8")):{};if(config.workspaceRoot===root)return;config.workspaceRoot=root,mkdirSync6(home,{recursive:!0}),writeFileSync5(configPath2,`${JSON.stringify(config,null,2)}
|
|
642
643
|
`,"utf-8")}catch{}}function clearWorkspaceRoot(){try{let configPath2=join15(genieHome2(),"config.json");if(!existsSync12(configPath2))return;let config=JSON.parse(readFileSync8(configPath2,"utf-8"));if(config.workspaceRoot===void 0)return;config.workspaceRoot=void 0,writeFileSync5(configPath2,`${JSON.stringify(config,null,2)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automagik/genie",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.260506.1",
|
|
4
4
|
"description": "Collaborative terminal toolkit for human + AI workflows. NOTE: the npm distribution is being soft-deprecated — the canonical install is `curl -fsSL https://get.automagik.dev/genie | bash` (cosign + SLSA verified). See https://automagik.dev/genie/security/distribution-sovereignty",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genie",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.260506.1",
|
|
4
4
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, turn them into wishes, execute with /work, validate with /review, and ship as one team.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Namastex Labs"
|