@automagik/genie 4.260503.9 → 4.260503.10
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
|
@@ -2092,7 +2092,7 @@ server.listen(PORT, '127.0.0.1', () => {
|
|
|
2092
2092
|
|
|
2093
2093
|
process.on('SIGTERM', () => { server.close(); process.exit(0); });
|
|
2094
2094
|
process.on('SIGINT', () => { server.close(); process.exit(0); });
|
|
2095
|
-
`,{mode:420});let{spawn:spawnChild}=__require("child_process");spawnChild("node",[scriptFile],{detached:!0,stdio:"ignore"}).unref();for(let i2=0;i2<30;i2++)if(await new Promise((r)=>setTimeout(r,100)),isRelayAlive(pidFile))return!0;return!1}catch{return!1}}async function generateWorkerId2(
|
|
2095
|
+
`,{mode:420});let{spawn:spawnChild}=__require("child_process");spawnChild("node",[scriptFile],{detached:!0,stdio:"ignore"}).unref();for(let i2=0;i2<30;i2++)if(await new Promise((r)=>setTimeout(r,100)),isRelayAlive(pidFile))return!0;return!1}catch{return!1}}async function generateWorkerId2(_team,_role){return crypto.randomUUID()}async function capturePanePid2(paneId){if(paneId==="inline")return null;try{let{execSync:execSync11}=__require("child_process"),output=execSync11(genieTmuxCmd(`display -t '${paneId}' -p '#{pane_pid}'`),{encoding:"utf-8"}).trim(),pid=Number.parseInt(output,10);return pid>0?pid:null}catch{return null}}function validateSpawnedPane(paneId,expectedPid){if(paneId==="inline")return;let{execSync:execSync11}=__require("child_process"),panes;try{panes=execSync11(genieTmuxCmd("list-panes -a -F '#{pane_id}'"),{encoding:"utf-8"})}catch{throw new SpawnPaneVanishedError(paneId,expectedPid,"tmux_query_failed")}if(!panes.split(`
|
|
2096
2096
|
`).map((line)=>line.trim()).includes(paneId))throw new SpawnPaneVanishedError(paneId,expectedPid,"pane_not_in_list");if(expectedPid!==null&&expectedPid>0)try{process.kill(expectedPid,0)}catch(err){if(err.code==="ESRCH")throw new SpawnPaneVanishedError(paneId,expectedPid,"pid_dead")}}function resolveExecutorTransport2(provider,spawnTransport){if(provider==="codex")return"api";if(provider==="claude-sdk")return"process";return spawnTransport==="inline"?"process":"tmux"}async function terminateActiveExecutorWithCleanup(agentIdentityId){try{let currentExec=await getCurrentExecutor(agentIdentityId);if(!currentExec||currentExec.state==="terminated"||currentExec.state==="done")return;let provider=getProvider(currentExec.provider);if(provider)try{await provider.terminate(currentExec)}catch{}await terminateActiveExecutor(agentIdentityId)}catch{}}async function createAndLinkExecutor2(agentIdentityId,provider,transport,opts){try{let executor=await createExecutor(agentIdentityId,provider,transport,opts);return await setCurrentExecutor(agentIdentityId,executor.id),executor.id}catch{return null}}async function registerSpawnWorker(ctx,paneId,windowInfo){let nt=ctx.validated.nativeTeam,workerEntry={id:ctx.workerId,paneId,session:ctx.validated.team,provider:ctx.validated.provider,transport:ctx.transport,role:ctx.validated.role,skill:ctx.validated.skill,team:ctx.validated.team,worktree:null,startedAt:ctx.now,state:"spawning",lastStateChange:ctx.now,repoPath:ctx.cwd,nativeTeamEnabled:nt?.enabled??!1,nativeAgentId:`${ctx.agentName}@${ctx.validated.team}`,nativeColor:nt?.color??ctx.spawnColor,parentSessionId:nt?.parentSessionId??ctx.parentSessionId,window:windowInfo?.windowName,windowName:windowInfo?.windowName,windowId:windowInfo?.windowId,autoResume:ctx.autoResume===!1?!1:void 0,resumeAttempts:0};await register(workerEntry);let role=ctx.validated.role??ctx.agentName;if(role!=="council")try{await hireAgent(ctx.validated.team,role)}catch{}return workerEntry}async function notifySpawnJoin(ctx,paneId){let nt=ctx.validated.nativeTeam;if(!nt?.enabled)return;await registerNativeMember(ctx.validated.team,{agentName:ctx.agentName,agentType:nt.agentType??ctx.validated.role??"general-purpose",color:nt.color??ctx.spawnColor??"blue",tmuxPaneId:paneId,cwd:ctx.cwd,planModeRequired:nt.planModeRequired});let leaderName=await resolveTeamLeaderName(ctx.validated.team);await writeNativeInbox(ctx.validated.team,leaderName,{from:ctx.agentName,text:`Worker ${ctx.agentName} (${ctx.validated.provider}) joined team ${ctx.validated.team}. cwd: ${ctx.cwd}. Ready for tasks.`,summary:`${ctx.agentName} (${ctx.validated.provider}) joined`,timestamp:new Date().toISOString(),color:nt.color??ctx.spawnColor??"blue",read:!1})}function registerOtelRelayPane(workerId,paneId,agentName,spawnColor,repoPath){let{writeFileSync:wfs}=__require("fs"),{join:pjoin}=__require("path"),{homedir:hdir}=__require("os"),rd=pjoin(hdir(),".genie","relay");wfs(pjoin(rd,`${workerId}-pane`),paneId),wfs(pjoin(rd,`${workerId}-meta`),JSON.stringify({agent:agentName,color:spawnColor,repoPath}))}function printSpawnInfo(ctx,paneId,workerEntry){let nt=ctx.validated.nativeTeam;if(console.log(`Agent "${ctx.workerId}" spawned.`),console.log(` Provider: ${ctx.launch.provider}`),console.log(` Command: ${ctx.fullCommand}`),console.log(` Team: ${ctx.validated.team}`),console.log(` Pane: ${paneId}`),ctx.validated.role)console.log(` Role: ${ctx.validated.role}`);if(ctx.executorId)console.log(` Executor: ${ctx.executorId}`);if(ctx.validated.skill)console.log(` Skill: ${ctx.validated.skill}`);if(ctx.claudeSessionId)console.log(` Session: ${ctx.claudeSessionId}`);if(console.log(` Layout: ${ctx.layoutMode}`),nt?.enabled)console.log(" Native: enabled"),console.log(` AgentID: ${workerEntry.nativeAgentId}`),console.log(` Color: ${nt.color}`);if(ctx.otelRelayActive)console.log(` OTel: relay on port ${OTEL_RELAY_PORT}`)}function shellQuote2(arg){return`'${arg.replace(/'/g,"'\\''")}'`}function writeTmuxLaunchScript(workerId,fullCommand){let{chmodSync:chmodSync3,mkdirSync:mkdirSync19,writeFileSync:writeFileSync17}=__require("fs"),{join:join51}=__require("path"),{homedir:homedir34}=__require("os"),dir=join51(homedir34(),".genie","spawn-scripts");mkdirSync19(dir,{recursive:!0});let safeId=workerId.replace(/[^a-zA-Z0-9._-]/g,"-"),scriptPath=join51(dir,`${safeId}-${Date.now().toString(36)}.sh`);return writeFileSync17(scriptPath,`#!/bin/sh
|
|
2097
2097
|
exec ${fullCommand}
|
|
2098
2098
|
`,{mode:448}),chmodSync3(scriptPath,448),scriptPath}function buildInitialSplitWindowCommand(windowId,cwd,fullCommand){let cwdFlag=cwd?` -c ${shellQuote2(cwd)}`:"";return genieTmuxCmd(`split-window -d -t ${shellQuote2(windowId)}${cwdFlag} -P -F '#{pane_id}' ${shellQuote2(fullCommand)}`)}async function resolveSpawnTeamWindow(team,cwd,sessionOverride){if(!team)return null;try{let sessionName=sessionOverride;if(!sessionName)sessionName=(await getTeam(team))?.tmuxSessionName;if(!sessionName)sessionName=await resolveRepoSession(cwd);if(!sessionName)sessionName=team;return await ensureTeamWindow(sessionName,team,cwd)}catch(err){return console.warn(`Warning: could not ensure team window for "${team}": ${err instanceof Error?err.message:err}`),null}}async function autoConfirmTrustPrompt(paneId){let{execSync:execSync11}=__require("child_process"),maxWaitMs=15000,pollMs=500,start=Date.now();while(Date.now()-start<15000){await new Promise((r)=>setTimeout(r,500));let content;try{content=execSync11(genieTmuxCmd(`capture-pane -t '${paneId}' -p`),{encoding:"utf-8"})}catch{return}if(content.includes("trust this folder")||content.includes("Quick safety check")){try{execSync11(genieTmuxCmd(`send-keys -t '${paneId}' Enter`),{encoding:"utf-8"})}catch{}return}if(content.includes("Claude Code")||content.includes("\u276F")||content.includes("Churning"))return}}function createTmuxPane(ctx,teamWindow){let{execSync:execSync11}=__require("child_process"),useLaunchScript=ctx.validated.provider==="claude"&&Boolean(ctx.validated.nativeTeam?.enabled),tmuxCommand=useLaunchScript?shellQuote2(writeTmuxLaunchScript(ctx.workerId,ctx.fullCommand)):shellQuote2(ctx.fullCommand),tmuxPrefix=genieTmuxCmd("");if(ctx.validated.windowTarget){let cwdFlag2=ctx.cwd?` -c ${shellQuote2(ctx.cwd)}`:"",cmd=`${tmuxPrefix}split-window -d -t ${shellQuote2(ctx.validated.windowTarget)}${cwdFlag2} -P -F '#{pane_id}' ${tmuxCommand}`;return execSync11(cmd,{encoding:"utf-8"}).trim()}if(ctx.validated.newWindow){let session=ctx.sessionOverride??teamWindow?.sessionName??ctx.validated.team,cwdFlag2=ctx.cwd?` -c ${shellQuote2(ctx.cwd)}`:"",sessionExists2=!1;try{execSync11(`${tmuxPrefix}has-session -t ${shellQuote2(`=${session}`)}`,{stdio:"ignore"}),sessionExists2=!0}catch{sessionExists2=!1}if(!sessionExists2)execSync11(`${tmuxPrefix}new-session -d -s ${shellQuote2(session)} -n home${cwdFlag2}`,{stdio:"ignore"});let cmd=`${tmuxPrefix}new-window -a -d -t ${shellQuote2(`${session}:`)} -n claude${cwdFlag2} -P -F '#{pane_id}' ${tmuxCommand}`;return execSync11(cmd,{encoding:"utf-8"}).trim()}if(teamWindow?.created){let cwdFlag2=ctx.cwd?` -c ${shellQuote2(ctx.cwd)}`:"",paneId=execSync11(`${tmuxPrefix}split-window -d -t ${shellQuote2(teamWindow.windowId)}${cwdFlag2} -P -F '#{pane_id}' ${tmuxCommand}`,{encoding:"utf-8"}).trim();try{execSync11(genieTmuxCmd(`kill-pane -t '${teamWindow.paneId}'`),{stdio:"ignore"})}catch{}return paneId}let callerPane=process.env.TMUX_PANE;if(!teamWindow&&!callerPane)throw Error("createTmuxPane: refusing to split with no target \u2014 neither teamWindow nor TMUX_PANE is set. "+"This indicates a missing --team or --window flag, or a caller outside tmux. See ~/.genie/reports/trace-genie-spawn-wrong-window.md");let splitTarget=teamWindow?`-t '${teamWindow.windowId}'`:`-t '${callerPane}'`,cwdFlag=ctx.cwd?`-c '${ctx.cwd}'`:"";if(useLaunchScript){let splitCmd2=`${tmuxPrefix}split-window -d ${splitTarget} ${cwdFlag} -P -F '#{pane_id}' ${tmuxCommand}`;return execSync11(splitCmd2,{encoding:"utf-8"}).trim()}let escapedCmd=ctx.fullCommand.replace(/'/g,"'\\''"),splitCmd=`${tmuxPrefix}split-window -d ${splitTarget} ${cwdFlag} -P -F '#{pane_id}' '${escapedCmd}'`;return execSync11(splitCmd,{encoding:"utf-8"}).trim()}async function applySpawnLayout(ctx,teamWindow){let{execSync:execSync11}=__require("child_process"),session=await getCurrentSessionName()??ctx.validated.team,layoutTarget=`${session}:${teamWindow?.windowName??""}`;if(!teamWindow){let wins=await listWindows(session);layoutTarget=wins[0]?wins[0].id:`${session}:`}try{execSync11(genieTmuxCmd(buildLayoutCommand(layoutTarget,ctx.layoutMode)),{stdio:"ignore"})}catch{}}async function createTmuxExecutor(ctx,paneId,pid,teamWindow){if(!ctx.agentIdentityId||!ctx.executorId)return;await createAndLinkExecutor2(ctx.agentIdentityId,ctx.validated.provider,resolveExecutorTransport2(ctx.validated.provider,"tmux"),{id:ctx.executorId,pid,tmuxSession:ctx.validated.team,tmuxPaneId:paneId,tmuxWindow:teamWindow?.windowName??null,tmuxWindowId:teamWindow?.windowId??null,claudeSessionId:ctx.claudeSessionId??null,state:"spawning",repoPath:ctx.cwd,paneColor:ctx.spawnColor})}async function finalizeTmuxSpawn(ctx,paneId,teamWindow,workerEntry){if(ctx.spawnColor&&paneId!=="inline")await applyPaneColor(paneId,ctx.spawnColor,teamWindow?.windowId);if(await saveTemplate({id:ctx.validated.role??ctx.workerId,provider:ctx.validated.provider,team:ctx.validated.team,role:ctx.validated.role,skill:ctx.validated.skill,cwd:ctx.cwd,extraArgs:ctx.extraArgs,nativeTeamEnabled:workerEntry.nativeTeamEnabled,lastSpawnedAt:new Date().toISOString()}),ctx.otelRelayActive&&paneId!=="%0")registerOtelRelayPane(ctx.workerId,paneId,ctx.agentName,ctx.spawnColor,ctx.cwd);if(teamWindow)console.log(` Window: ${teamWindow.windowName} (${teamWindow.windowId})`);printSpawnInfo(ctx,paneId,workerEntry)}async function awaitAgentReadiness(paneId,role,tolerateReadinessTimeout){if(paneId==="inline")return;let result2=await waitForAgentReady(paneId);if(result2.ready){console.log(` \u2713 Agent ready (${(result2.elapsedMs/1000).toFixed(1)}s)`);return}if(tolerateReadinessTimeout){console.log(` \u26A0 Agent readiness timeout (${Math.round(result2.elapsedMs/1000)}s) \u2014 proceeding anyway`);return}throw console.error(` \u2717 Agent readiness timeout (${Math.round(result2.elapsedMs/1000)}s) \u2014 failing strict mode`),new AgentReadinessTimeoutError(role,paneId,result2.elapsedMs)}async function launchTmuxSpawn(ctx){let isolatedSessionSpawn=ctx.validated.newWindow===!0&&Boolean(ctx.sessionOverride),teamWindow=ctx.spawnIntoCurrentWindow||isolatedSessionSpawn?null:await resolveSpawnTeamWindow(ctx.validated.team,ctx.cwd,ctx.sessionOverride),emitFailed=(reason,extra={})=>{recordAuditEvent("worker",ctx.workerId,"worker.spawn.failed",getActor(),{reason,worker_id:ctx.workerId,agent_role:ctx.validated.role??ctx.workerId,cwd:ctx.cwd,executor_id:ctx.executorId,...extra}).catch(()=>{})},paneId;try{paneId=createTmuxPane(ctx,teamWindow)}catch(err){let msg=err instanceof Error?err.message:"unknown error";return emitFailed("createTmuxPane_threw",{error:msg}),console.error(`Failed to create tmux pane: ${msg}`),process.exit(1)}let pid=await capturePanePid2(paneId);try{validateSpawnedPane(paneId,pid)}catch(err){let reason=err instanceof SpawnPaneVanishedError?err.reason:"pane_validation_threw";throw emitFailed("pane_vanished",{pane_id:paneId,pid,vanish_reason:reason,error:err instanceof Error?err.message:String(err)}),err}if(await createTmuxExecutor(ctx,paneId,pid,teamWindow),await applySpawnLayout(ctx,teamWindow),ctx.validated.provider==="claude")await autoConfirmTrustPrompt(paneId);let workerEntry=await registerSpawnWorker(ctx,paneId,teamWindow);await notifySpawnJoin(ctx,paneId),await finalizeTmuxSpawn(ctx,paneId,teamWindow,workerEntry);try{await awaitAgentReadiness(paneId,ctx.validated.role??ctx.workerId,ctx.tolerateReadinessTimeout)}catch(err){let reason=err instanceof AgentReadinessTimeoutError?"readiness_timeout":"readiness_probe_threw";throw emitFailed(reason,{pane_id:paneId,pid,error:err instanceof Error?err.message:String(err)}),err}if(ctx.executorId)await updateExecutorState(ctx.executorId,"running").catch(()=>{});return await update(ctx.workerId,{state:"idle"}).catch(()=>{}),recordAuditEvent("worker",ctx.workerId,"worker.spawn.ok",getActor(),{worker_id:ctx.workerId,agent_role:ctx.validated.role??ctx.workerId,pane_id:paneId,pid,cwd:ctx.cwd,executor_id:ctx.executorId}).catch(()=>{}),paneId}async function runSdkQuery(ctx,permConfig,streamOpts,sdkConfig,runtimeExtraOptions){let{ClaudeSdkProvider:ClaudeSdkProvider2}=await Promise.resolve().then(() => (init_claude_sdk(),exports_claude_sdk)),{startSession:startSession2,recordTurn:recordTurn2,updateTurnCount:updateTurnCount2,endSession:endSession2}=await Promise.resolve().then(() => exports_sdk_session_capture),{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sdkProvider=new ClaudeSdkProvider2,spawnContext={agentId:ctx.agentIdentityId??ctx.workerId,executorId:ctx.executorId??crypto.randomUUID(),team:ctx.validated.team,role:ctx.validated.role,skill:ctx.validated.skill,cwd:ctx.cwd,model:ctx.validated.model,systemPrompt:ctx.validated.systemPrompt,systemPromptFile:ctx.validated.systemPromptFile,initialPrompt:ctx.validated.initialPrompt,name:ctx.validated.name},safePgCall=async(_op,fn,fallback)=>{try{let sql=await getConnection2();return await fn(sql)}catch{return fallback}},prompt2=ctx.validated.initialPrompt??`You are ${ctx.validated.role??"an agent"} on team "${ctx.validated.team}". Awaiting instructions.`,resumeSessionId=typeof runtimeExtraOptions?.resume==="string"?runtimeExtraOptions.resume:void 0,dbSessionId=null,turnIndex=0;if(resumeSessionId){let resolvedClaudeSessionId=resumeSessionId,byPgId=await safePgCall("resolve-session-resume",(sql)=>sql`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automagik/genie",
|
|
3
|
-
"version": "4.260503.
|
|
3
|
+
"version": "4.260503.10",
|
|
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.260503.
|
|
3
|
+
"version": "4.260503.10",
|
|
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"
|