@automagik/genie 4.260428.13 → 4.260428.14

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
@@ -1696,7 +1696,7 @@ ${after}
1696
1696
 
1697
1697
  ${desired}
1698
1698
  `:`${desired}
1699
- `;if(existing.trim()===candidate.trim())return!1;return await mkdir5(codexHomeDir(),{recursive:!0}),await writeFile6(path3,candidate),!0}async function codexHooksInjected(){let path3=codexConfigPath();if(!existsSync34(path3))return!1;try{let content=await readFile10(path3,"utf-8");return content.includes(BEGIN_MARKER)&&content.includes(END_MARKER)}catch{return!1}}var DISPATCH_TIMEOUT2=15,CODEX_DISPATCHED_EVENTS,BEGIN_MARKER="# === GENIE HOOK BRIDGE BEGIN ===",END_MARKER="# === GENIE HOOK BRIDGE END ===";var init_codex_inject=__esm(()=>{init_inject();CODEX_DISPATCHED_EVENTS=["PreToolUse","PostToolUse","UserPromptSubmit","SessionStart","Stop","PermissionRequest"]});var exports_idle_timeout={};__export(exports_idle_timeout,{suspendWorker:()=>suspendWorker,getIdleTimeoutMs:()=>getIdleTimeoutMs,checkIdleWorkers:()=>checkIdleWorkers,WATCHDOG_POLL_INTERVAL_MS:()=>WATCHDOG_POLL_INTERVAL_MS});function getIdleTimeoutMs(){let env=process.env.GENIE_IDLE_TIMEOUT_MS;if(env!==void 0){if(env==="")return DEFAULT_IDLE_TIMEOUT_MS;let parsed=Number(env);if(!Number.isNaN(parsed)&&parsed>=0)return parsed}return DEFAULT_IDLE_TIMEOUT_MS}async function suspendWorker(executorId,deps=defaultDeps3){let executor=(await deps.listExecutors()).find((e)=>e.id===executorId);if(!executor)return!1;if(executor.state==="terminated")return!0;if(executor.tmuxPaneId)try{await deps.executeTmux(`kill-pane -t '${executor.tmuxPaneId}'`)}catch{}return await deps.terminateExecutor(executorId),!0}async function checkIdleWorkers(deps=defaultDeps3){let timeoutMs=getIdleTimeoutMs();if(timeoutMs===0)return[];let executors=await deps.listExecutors(),suspended=[];for(let e of executors){if(e.state!=="idle")continue;if(Date.now()-new Date(e.updatedAt).getTime()<timeoutMs)continue;if(e.tmuxPaneId){if(!await deps.isPaneAlive(e.tmuxPaneId)){await deps.terminateExecutor(e.id),suspended.push(e.id);continue}}if(await suspendWorker(e.id,deps))suspended.push(e.id)}return suspended}var defaultDeps3,DEFAULT_IDLE_TIMEOUT_MS=1800000,WATCHDOG_POLL_INTERVAL_MS=60000;var init_idle_timeout=__esm(()=>{init_executor_registry();init_tmux();defaultDeps3={listExecutors:()=>listExecutors(),terminateExecutor,updateExecutorState,executeTmux:executeTmux2,isPaneAlive}});var exports_agents={};__export(exports_agents,{resolveTeamName:()=>resolveTeamName3,resolveSpawnIdentity:()=>resolveSpawnIdentity,resolveAgentWorkingDir:()=>resolveAgentWorkingDir,recoverSurgery:()=>recoverSurgery,pickParallelShortId:()=>pickParallelShortId,handleWorkerStop:()=>handleWorkerStop,handleWorkerSpawn:()=>handleWorkerSpawn,handleWorkerResume:()=>handleWorkerResume,handleWorkerRecover:()=>handleWorkerRecover,handleWorkerKill:()=>handleWorkerKill,handleLsCommand:()=>handleLsCommand,findDeadResumable:()=>findDeadResumable,buildWorkerStatusMap:()=>buildWorkerStatusMap,buildResumeContext:()=>buildResumeContext,buildInitialSplitWindowCommand:()=>buildInitialSplitWindowCommand,buildFullResumeParams:()=>buildFullResumeParams,RecoverAgentNotFoundError:()=>RecoverAgentNotFoundError,OwnerSpawnCollisionError:()=>OwnerSpawnCollisionError});async function isPaneAliveOrDead(paneId){try{return await isPaneAlive(paneId)}catch(err){let message=err instanceof Error?err.message:String(err);if(err instanceof TmuxUnreachableError||message.includes("no server running")||message.includes("server exited")||message.includes("error connecting"))return!1;throw err}}async function resolveTeamLeaderName(teamNameOrDefault){return resolveLeaderName(teamNameOrDefault)}function isRelayAlive(pidFile){let{readFileSync:readFileSync21,existsSync:existsSync35}=__require("fs");if(!existsSync35(pidFile))return!1;try{let pid=Number.parseInt(readFileSync21(pidFile,"utf-8").trim());if(pid>0)return process.kill(pid,0),!0}catch{}return!1}async function ensureOtelRelay(team){let{writeFileSync:writeFileSync13,mkdirSync:mkdirSync14}=__require("fs"),{join:join42}=__require("path"),{homedir:homedir28}=__require("os"),relayDir=join42(homedir28(),".genie","relay");mkdirSync14(relayDir,{recursive:!0});let pidFile=join42(relayDir,"otel-relay.pid"),scriptFile=join42(relayDir,"otel-relay.mjs");if(isRelayAlive(pidFile))return!0;let inboxDir=join42(process.env.CLAUDE_CONFIG_DIR??join42(homedir28(),".claude"),"teams",team,"inboxes"),leaderInboxName=sanitizeTeamName(await resolveTeamLeaderName(team)),escapedRelayDir=relayDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedInboxDir=inboxDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedPidFile=pidFile.replace(/\\/g,"\\\\").replace(/'/g,"\\'");try{writeFileSync13(scriptFile,`import { createServer } from 'http';
1699
+ `;if(existing.trim()===candidate.trim())return!1;return await mkdir5(codexHomeDir(),{recursive:!0}),await writeFile6(path3,candidate),!0}async function codexHooksInjected(){let path3=codexConfigPath();if(!existsSync34(path3))return!1;try{let content=await readFile10(path3,"utf-8");return content.includes(BEGIN_MARKER)&&content.includes(END_MARKER)}catch{return!1}}var DISPATCH_TIMEOUT2=15,CODEX_DISPATCHED_EVENTS,BEGIN_MARKER="# === GENIE HOOK BRIDGE BEGIN ===",END_MARKER="# === GENIE HOOK BRIDGE END ===";var init_codex_inject=__esm(()=>{init_inject();CODEX_DISPATCHED_EVENTS=["PreToolUse","PostToolUse","UserPromptSubmit","SessionStart","Stop","PermissionRequest"]});var exports_idle_timeout={};__export(exports_idle_timeout,{suspendWorker:()=>suspendWorker,getIdleTimeoutMs:()=>getIdleTimeoutMs,checkIdleWorkers:()=>checkIdleWorkers,WATCHDOG_POLL_INTERVAL_MS:()=>WATCHDOG_POLL_INTERVAL_MS});function getIdleTimeoutMs(){let env=process.env.GENIE_IDLE_TIMEOUT_MS;if(env!==void 0){if(env==="")return DEFAULT_IDLE_TIMEOUT_MS;let parsed=Number(env);if(!Number.isNaN(parsed)&&parsed>=0)return parsed}return DEFAULT_IDLE_TIMEOUT_MS}async function suspendWorker(executorId,deps=defaultDeps3){let executor=(await deps.listExecutors()).find((e)=>e.id===executorId);if(!executor)return!1;if(executor.state==="terminated")return!0;if(executor.tmuxPaneId)try{await deps.executeTmux(`kill-pane -t '${executor.tmuxPaneId}'`)}catch{}return await deps.terminateExecutor(executorId),!0}async function checkIdleWorkers(deps=defaultDeps3){let timeoutMs=getIdleTimeoutMs();if(timeoutMs===0)return[];let executors=await deps.listExecutors(),suspended=[];for(let e of executors){if(e.state!=="idle")continue;if(Date.now()-new Date(e.updatedAt).getTime()<timeoutMs)continue;if(e.tmuxPaneId){if(!await deps.isPaneAlive(e.tmuxPaneId)){await deps.terminateExecutor(e.id),suspended.push(e.id);continue}}if(await suspendWorker(e.id,deps))suspended.push(e.id)}return suspended}var defaultDeps3,DEFAULT_IDLE_TIMEOUT_MS=1800000,WATCHDOG_POLL_INTERVAL_MS=60000;var init_idle_timeout=__esm(()=>{init_executor_registry();init_tmux();defaultDeps3={listExecutors:()=>listExecutors(),terminateExecutor,updateExecutorState,executeTmux:executeTmux2,isPaneAlive}});var exports_agents={};__export(exports_agents,{resolveTeamName:()=>resolveTeamName3,resolveSpawnIdentity:()=>resolveSpawnIdentity,resolveAgentWorkingDir:()=>resolveAgentWorkingDir,rejectDuplicateRole:()=>rejectDuplicateRole,recoverSurgery:()=>recoverSurgery,pickParallelShortId:()=>pickParallelShortId,handleWorkerStop:()=>handleWorkerStop,handleWorkerSpawn:()=>handleWorkerSpawn,handleWorkerResume:()=>handleWorkerResume,handleWorkerRecover:()=>handleWorkerRecover,handleWorkerKill:()=>handleWorkerKill,handleLsCommand:()=>handleLsCommand,findDeadResumable:()=>findDeadResumable,buildWorkerStatusMap:()=>buildWorkerStatusMap,buildResumeContext:()=>buildResumeContext,buildInitialSplitWindowCommand:()=>buildInitialSplitWindowCommand,buildFullResumeParams:()=>buildFullResumeParams,RecoverAgentNotFoundError:()=>RecoverAgentNotFoundError,OwnerSpawnCollisionError:()=>OwnerSpawnCollisionError});async function isPaneAliveOrDead(paneId){try{return await isPaneAlive(paneId)}catch(err){let message=err instanceof Error?err.message:String(err);if(err instanceof TmuxUnreachableError||message.includes("no server running")||message.includes("server exited")||message.includes("error connecting"))return!1;throw err}}async function resolveTeamLeaderName(teamNameOrDefault){return resolveLeaderName(teamNameOrDefault)}function isRelayAlive(pidFile){let{readFileSync:readFileSync21,existsSync:existsSync35}=__require("fs");if(!existsSync35(pidFile))return!1;try{let pid=Number.parseInt(readFileSync21(pidFile,"utf-8").trim());if(pid>0)return process.kill(pid,0),!0}catch{}return!1}async function ensureOtelRelay(team){let{writeFileSync:writeFileSync13,mkdirSync:mkdirSync14}=__require("fs"),{join:join42}=__require("path"),{homedir:homedir28}=__require("os"),relayDir=join42(homedir28(),".genie","relay");mkdirSync14(relayDir,{recursive:!0});let pidFile=join42(relayDir,"otel-relay.pid"),scriptFile=join42(relayDir,"otel-relay.mjs");if(isRelayAlive(pidFile))return!0;let inboxDir=join42(process.env.CLAUDE_CONFIG_DIR??join42(homedir28(),".claude"),"teams",team,"inboxes"),leaderInboxName=sanitizeTeamName(await resolveTeamLeaderName(team)),escapedRelayDir=relayDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedInboxDir=inboxDir.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),escapedPidFile=pidFile.replace(/\\/g,"\\\\").replace(/'/g,"\\'");try{writeFileSync13(scriptFile,`import { createServer } from 'http';
1700
1700
  import { execSync } from 'child_process';
1701
1701
  import { readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'fs';
1702
1702
  import { createHash } from 'crypto';
@@ -1983,9 +1983,8 @@ exec ${fullCommand}
1983
1983
  `)}let extraOptions={...streaming&&{includePartialMessages:!0},...runtimeExtraOptions},hasExtraOptions=Object.keys(extraOptions).length>0,{messages:messages2}=sdkProvider.runQuery(spawnContext,prompt2,permConfig,hasExtraOptions?extraOptions:void 0,sdkConfig);if(ctx.executorId)await updateExecutorState(ctx.executorId,"running").catch(()=>{});let claudeSessionId,toolNameById=new Map,record=async(role,content,toolName)=>{if(!dbSessionId)return;await recordTurn2(safePgCall,dbSessionId,turnIndex++,role,content,toolName)},recordToolUseBlock=async(block)=>{let b2=block,name=String(b2.name??""),id=String(b2.id??"");if(id)toolNameById.set(id,name);await record("tool_input",JSON.stringify(b2.input??{}).slice(0,500),name)},recordAssistantBlocks=async(message)=>{if(!message.message)return;for(let block of message.message.content)if(block.type==="tool_use")await recordToolUseBlock(block);else if(block.type==="text"&&block.text)await record("assistant",block.text)},recordToolResultBlock=async(block)=>{let b2=block;if(b2.type!=="tool_result")return;let toolId=String(b2.tool_use_id??""),toolName=toolNameById.get(toolId)??"",output=typeof b2.content==="string"?b2.content.slice(0,500):"";await record("tool_output",output,toolName)},recordToolResults=async(message)=>{if(!message.message?.content||!Array.isArray(message.message.content))return;for(let block of message.message.content)await recordToolResultBlock(block)},processMessage=async(message)=>{if(message.type==="system"){let sid=message.session_id;if(sid)claudeSessionId=sid;return}if(message.type==="assistant"){await recordAssistantBlocks(message);return}if(message.type==="user"){await recordToolResults(message);return}if(message.type==="result"&&message.subtype==="success"&&message.session_id)claudeSessionId=message.session_id};if(streaming){let{formatSdkMessage:formatSdkMessage2}=await Promise.resolve().then(() => exports_claude_sdk_stream),format=streamOpts?.streamFormat??"text";try{for await(let message of messages2){let formatted=formatSdkMessage2(message,format);if(formatted!==null){if(process.stdout.write(formatted),format==="json")process.stdout.write(`
1984
1984
  `)}await processMessage(message)}}catch(err){if(!(err instanceof Error&&err.name==="AbortError"))console.error(`SDK query error: ${err instanceof Error?err.message:err}`)}}else try{for await(let message of messages2){if(message.type==="assistant"&&message.message){for(let block of message.message.content)if(block.type==="text"&&block.text)process.stdout.write(block.text)}if(message.type==="result"&&message.subtype==="success"&&message.result)console.log(message.result);await processMessage(message)}}catch(err){if(!(err instanceof Error&&err.name==="AbortError"))console.error(`SDK query error: ${err instanceof Error?err.message:err}`)}if(dbSessionId)await updateTurnCount2(safePgCall,dbSessionId,turnIndex),await endSession2(safePgCall,dbSessionId,"completed");if(claudeSessionId&&spawnContext.executorId){let csId=claudeSessionId;await safePgCall("update-claude-session-id",(sql)=>sql`UPDATE executors SET claude_session_id = ${csId} WHERE id = ${spawnContext.executorId}`,void 0)}if(claudeSessionId&&dbSessionId){let csId=claudeSessionId,sessId=dbSessionId;await safePgCall("update-session-claude-id",(sql)=>sql`UPDATE sessions SET claude_session_id = ${csId} WHERE id = ${sessId}`,void 0)}}async function rollbackSpawn(ctx,opts){if(opts.workerRegistered)await unregister(ctx.workerId).catch(()=>{});if(ctx.executorId)await updateExecutorState(ctx.executorId,"error").catch(()=>{})}async function launchSdkSpawn(ctx,permissionsConfig,streamOpts,sdkConfig,runtimeExtraOptions){let workerRegistered=!1;try{if(ctx.agentIdentityId&&ctx.executorId)await createAndLinkExecutor2(ctx.agentIdentityId,"claude-sdk","process",{id:ctx.executorId,claudeSessionId:null,state:"spawning",repoPath:ctx.cwd});if(await registerSpawnWorker(ctx,"sdk"),workerRegistered=!0,ctx.executorId)process.env.GENIE_EXECUTOR_ID=ctx.executorId;if(console.log(`Agent "${ctx.workerId}" starting via Claude Agent SDK...`),console.log(` Provider: claude-sdk | Team: ${ctx.validated.team} | Role: ${ctx.validated.role??"-"}`),ctx.executorId)console.log(` Executor: ${ctx.executorId}`);console.log("");let{resolvePermissionConfig:resolvePermissionConfig2}=await Promise.resolve().then(() => (init_claude_sdk_permissions(),exports_claude_sdk_permissions)),permConfig=resolvePermissionConfig2(permissionsConfig);await runSdkQuery(ctx,permConfig,streamOpts,sdkConfig,runtimeExtraOptions)}catch(err){throw await rollbackSpawn(ctx,{workerRegistered}),err}if(ctx.executorId)await updateExecutorState(ctx.executorId,"done").catch(()=>{});return await unregister(ctx.workerId),console.log(`
1985
1985
  Agent "${ctx.workerId}" SDK session ended.`),ctx.workerId}async function launchInlineSpawn(ctx){let nt=ctx.validated.nativeTeam,paneId="inline",workerRegistered=!1,workerEntry;try{if(ctx.agentIdentityId&&ctx.executorId)await createAndLinkExecutor2(ctx.agentIdentityId,ctx.validated.provider,resolveExecutorTransport2(ctx.validated.provider,"inline"),{id:ctx.executorId,claudeSessionId:ctx.claudeSessionId??null,state:"spawning",repoPath:ctx.cwd});if(workerEntry=await registerSpawnWorker(ctx,"inline"),workerRegistered=!0,await notifySpawnJoin(ctx,"inline"),console.log(`Agent "${ctx.workerId}" starting inline...`),console.log(` Provider: ${ctx.launch.provider} | Team: ${ctx.validated.team} | Role: ${ctx.validated.role??"-"}`),nt?.enabled)console.log(` Native: enabled | AgentID: ${workerEntry.nativeAgentId}`);console.log("")}catch(err){throw await rollbackSpawn(ctx,{workerRegistered}),err}let{spawnSync:spawnSync5}=__require("child_process"),envVars={...process.env,...ctx.launch.env??{}},result2=spawnSync5("sh",["-c",ctx.launch.command],{env:envVars,stdio:"inherit"});if(result2.error)throw await rollbackSpawn(ctx,{workerRegistered}),result2.error;if(ctx.agentIdentityId&&ctx.executorId)await updateExecutorState(ctx.executorId,"done").catch(()=>{});if(await unregister(ctx.workerId),nt?.enabled&&ctx.agentName)await clearNativeInbox(ctx.validated.team,ctx.agentName).catch(()=>{}),await unregisterNativeMember(ctx.validated.team,ctx.agentName).catch(()=>{});return console.log(`
1986
- Agent "${ctx.workerId}" session ended.`),process.exit(result2.status??0)}async function findDeadResumable(team,role,isAliveFn=isPaneAliveOrDead){let prefiltered=(await list()).filter((w)=>w.role===role&&w.team===team&&w.provider==="claude"&&w.transport==="tmux"),candidate=null;for(let w of prefiltered)if((await getCurrentExecutor(w.id))?.claudeSessionId){candidate=w;break}if(!candidate)return null;if(await isAliveFn(candidate.paneId)){if(candidate.kind==="permanent")throw new OwnerSpawnCollisionError(role,team,candidate.id,candidate.paneId,candidate.state);return null}return candidate}async function rejectDuplicateRole(team,role){let existing=await list();for(let w of existing)if(w.role===role&&w.team===team){let alive=await resolveWorkerLivenessByTransport(w);if(alive&&w.session&&/^%\d+$/.test(w.paneId)){if(await getPaneSession(w.paneId)!==w.session){await unregister(w.id);continue}console.error(`Error: Worker with role "${role}" already exists in team "${team}" (state: ${w.state}, pane: ${w.paneId})
1987
- Use a different --role name for a second worker, e.g.: --role ${role}-2`),process.exit(1)}if(alive)console.error(`Error: Worker with role "${role}" already exists in team "${team}" (state: ${w.state}, pane: ${w.paneId})
1988
- Use a different --role name for a second worker, e.g.: --role ${role}-2`),process.exit(1);await unregister(w.id)}}async function getPaneSession(paneId){try{return(await executeTmux2(`display-message -t '${paneId}' -p '#{session_name}'`)).trim()||null}catch{return null}}async function resolveNativeTeam(team,_repoPath,options){let leaderName=await resolveLeaderName(team),sanitizedTeam=sanitizeTeamName(team),leaderAgent=await getAgentByName(leaderName,sanitizedTeam).catch(()=>null),parentSessionId;if(leaderAgent&&!options.isIdentitySpawn)parentSessionId=(await shouldResume(leaderAgent.id).catch(()=>null))?.sessionId;if(!parentSessionId)parentSessionId=await discoverClaudeParentSessionId()??`genie-${team}`;await ensureNativeTeam(team,`Genie team: ${team}`,parentSessionId);let spawnColor=options.color??await assignColor(team),nativeTeam;if(options.provider==="claude")nativeTeam={enabled:!0,parentSessionId,color:spawnColor,agentType:options.role??"general-purpose",planModeRequired:options.planMode,permissionMode:options.permissionMode,agentName:options.role};return{parentSessionId,spawnColor,nativeTeam}}async function resolveAgentForSpawn(name,options){let resolved=await resolve5(name);if(!resolved)console.error(`Error: Agent "${name}" not found in directory or built-ins.`),console.error(` Register with: genie dir add ${name} --dir <path>`),console.error(" Or use a built-in: engineer, reviewer, qa, fix, ..."),process.exit(1);let entry2=resolved.entry,identityPath=null;if(resolved.builtin)identityPath=resolveBuiltinAgentPath(name);else if(entry2.dir)identityPath=loadIdentity(entry2);let repoPath=resolveAgentWorkingDir(entry2,options.cwd),model=options.model;if(!model){let ctx=buildSpawnResolveContext(name,entry2);model=resolveField(entry2,"model",ctx)}return{entry:entry2,repoPath,identityPath,model}}function buildSpawnResolveContext(agentName,_entry){let ctx={};try{let ws=findWorkspace();if(ws){let wsConfig=getWorkspaceConfig(ws.root);ctx.workspaceDefaults=wsConfig.agents?.defaults}}catch{}if(agentName.includes("/")){let parentName=agentName.split("/")[0];try{let{readFileSync:readFileSync21,existsSync:existsSync35}=__require("fs"),{join:join42}=__require("path"),ws=findWorkspace();if(ws){let parentAgentsMd=join42(ws.root,"agents",parentName,"AGENTS.md");if(existsSync35(parentAgentsMd)){let{parseFrontmatter:parseFrontmatter3}=(init_frontmatter(),__toCommonJS(exports_frontmatter)),parentFm=parseFrontmatter3(readFileSync21(parentAgentsMd,"utf-8"));ctx.parent={name:parentName,fields:parentFm}}}}catch{}}return ctx}function resolveAgentWorkingDir(entry2,explicitCwd){if(explicitCwd)return explicitCwd;if(entry2.dir)return entry2.dir;let repo=entry2.repo;if(repo&&__require("fs").existsSync(repo))return repo;return process.cwd()}async function buildSpawnParams2(name,team,options,agent,preassignedSessionId,agentTemplate){let resolvedProvider=options.provider??agent.entry.provider??"claude",params={provider:resolvedProvider,team,role:name,agentTemplate:agentTemplate??name,skill:options.skill,extraArgs:options.extraArgs,model:agent.model,systemPromptFile:agent.identityPath??void 0,promptMode:agent.entry.promptMode,initialPrompt:options.prompt??options.initialPrompt,newWindow:options.newWindow,windowTarget:options.window},isIdentitySpawn=options.role!==void 0&&options.role!==name,{parentSessionId,spawnColor,nativeTeam}=await resolveNativeTeam(team,agent.repoPath,{...options,provider:resolvedProvider,role:name,isIdentitySpawn});if(nativeTeam)params.nativeTeam=nativeTeam;try{let{injectTeamHooks:injectTeamHooks2}=await Promise.resolve().then(() => (init_inject(),exports_inject));if(await injectTeamHooks2(team))console.log(` Hooks: injected genie hook dispatch into team "${team}"`)}catch(err){console.warn(`Warning: could not inject hooks for team "${team}": ${err instanceof Error?err.message:err}`)}if(params.provider==="codex")try{let{injectCodexHooks:injectCodexHooks2}=await Promise.resolve().then(() => (init_codex_inject(),exports_codex_inject));if(await injectCodexHooks2())console.log(" Hooks: injected genie hook dispatch into ~/.codex/config.toml")}catch(err){console.warn(`Warning: could not inject codex hooks: ${err instanceof Error?err.message:err}`)}if(params.provider==="claude")params.sessionId=preassignedSessionId??crypto.randomUUID();if(params.provider==="claude"){if(await startOtelReceiver())params.otelPort=getOtelPort(),params.otelLogPrompts=!0}return{params,parentSessionId,spawnColor}}async function maybeStartOtelRelay(nt,validated,insideTmux){if(!nt?.enabled&&validated.provider==="codex"&&insideTmux)return ensureCodexOtelConfig(),await ensureOtelRelay(validated.team);return!1}function buildSdkRuntimeExtra(options){let extra={};if(options.sdkMaxTurns!=null)extra.maxTurns=options.sdkMaxTurns;if(options.sdkMaxBudget!=null)extra.maxBudgetUsd=options.sdkMaxBudget;if(options.sdkEffort)extra.effort=options.sdkEffort;if(options.sdkResume)extra.resume=options.sdkResume;return Object.keys(extra).length>0?extra:void 0}async function dispatchSpawn(ctx,validated,options,agent,insideTmux){if(validated.provider==="claude-sdk"){let streamFormat=options.streamFormat??"text",streamOpts=options.stream||options.sdkStream?{stream:!0,streamFormat}:void 0;return await launchSdkSpawn(ctx,agent.entry.permissions,streamOpts,agent.entry.sdk,buildSdkRuntimeExtra(options))}if(insideTmux)return await launchTmuxSpawn(ctx);return await launchInlineSpawn(ctx)}async function resolveTeamName3(opts){if(opts.explicitTeam)return opts.explicitTeam;if(opts.entryTeam)return opts.entryTeam;let env=opts.env??process.env;if(env.GENIE_TEAM)return env.GENIE_TEAM;return await(opts.discover??discoverTeamName)()??null}async function pickParallelShortId(baseName,team,uuid){if(!UUID_REGEX.test(uuid))throw Error(`pickParallelShortId: expected a well-formed UUID (8-4-4-4-12 hex), got ${JSON.stringify(uuid)}`);let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2();for(let k=4;k<=uuid.length;k++){let slice=uuid.slice(0,k),id=`${baseName}-${slice}`;if((await sql`
1986
+ Agent "${ctx.workerId}" session ended.`),process.exit(result2.status??0)}async function findDeadResumable(team,role,isAliveFn=isPaneAliveOrDead){let prefiltered=(await list()).filter((w)=>w.role===role&&w.team===team&&w.provider==="claude"&&w.transport==="tmux"),candidate=null;for(let w of prefiltered)if((await getCurrentExecutor(w.id))?.claudeSessionId){candidate=w;break}if(!candidate)return null;if(await isAliveFn(candidate.paneId)){if(candidate.kind==="permanent")throw new OwnerSpawnCollisionError(role,team,candidate.id,candidate.paneId,candidate.state);return null}return candidate}async function rejectDuplicateRole(team,role){let existing=await list();for(let w of existing){if(w.team!==team)continue;let matchesRole=w.role===role,matchesName=w.id===role;if(!matchesRole&&!matchesName)continue;if(await classifyCollisionLiveness(w)==="alive"){let collisionLabel=matchesName&&!matchesRole?`name "${w.id}"`:`role "${role}"`;console.error(`Error: Worker with ${collisionLabel} already exists in team "${team}" (state: ${w.state}, pane: ${w.paneId})
1987
+ Use a different --role name for a second worker, e.g.: --role ${role}-2`),process.exit(1)}await unregister(w.id)}}async function classifyCollisionLiveness(w){if(!await resolveWorkerLivenessByTransport(w))return"dead";if(w.session&&/^%\d+$/.test(w.paneId)){if(await getPaneSession(w.paneId)!==w.session)return"recycled"}return"alive"}async function getPaneSession(paneId){try{return(await executeTmux2(`display-message -t '${paneId}' -p '#{session_name}'`)).trim()||null}catch{return null}}async function resolveNativeTeam(team,_repoPath,options){let leaderName=await resolveLeaderName(team),sanitizedTeam=sanitizeTeamName(team),leaderAgent=await getAgentByName(leaderName,sanitizedTeam).catch(()=>null),parentSessionId;if(leaderAgent&&!options.isIdentitySpawn)parentSessionId=(await shouldResume(leaderAgent.id).catch(()=>null))?.sessionId;if(!parentSessionId)parentSessionId=await discoverClaudeParentSessionId()??`genie-${team}`;await ensureNativeTeam(team,`Genie team: ${team}`,parentSessionId);let spawnColor=options.color??await assignColor(team),nativeTeam;if(options.provider==="claude")nativeTeam={enabled:!0,parentSessionId,color:spawnColor,agentType:options.role??"general-purpose",planModeRequired:options.planMode,permissionMode:options.permissionMode,agentName:options.role};return{parentSessionId,spawnColor,nativeTeam}}async function resolveAgentForSpawn(name,options){let resolved=await resolve5(name);if(!resolved)console.error(`Error: Agent "${name}" not found in directory or built-ins.`),console.error(` Register with: genie dir add ${name} --dir <path>`),console.error(" Or use a built-in: engineer, reviewer, qa, fix, ..."),process.exit(1);let entry2=resolved.entry,identityPath=null;if(resolved.builtin)identityPath=resolveBuiltinAgentPath(name);else if(entry2.dir)identityPath=loadIdentity(entry2);let repoPath=resolveAgentWorkingDir(entry2,options.cwd),model=options.model;if(!model){let ctx=buildSpawnResolveContext(name,entry2);model=resolveField(entry2,"model",ctx)}return{entry:entry2,repoPath,identityPath,model}}function buildSpawnResolveContext(agentName,_entry){let ctx={};try{let ws=findWorkspace();if(ws){let wsConfig=getWorkspaceConfig(ws.root);ctx.workspaceDefaults=wsConfig.agents?.defaults}}catch{}if(agentName.includes("/")){let parentName=agentName.split("/")[0];try{let{readFileSync:readFileSync21,existsSync:existsSync35}=__require("fs"),{join:join42}=__require("path"),ws=findWorkspace();if(ws){let parentAgentsMd=join42(ws.root,"agents",parentName,"AGENTS.md");if(existsSync35(parentAgentsMd)){let{parseFrontmatter:parseFrontmatter3}=(init_frontmatter(),__toCommonJS(exports_frontmatter)),parentFm=parseFrontmatter3(readFileSync21(parentAgentsMd,"utf-8"));ctx.parent={name:parentName,fields:parentFm}}}}catch{}}return ctx}function resolveAgentWorkingDir(entry2,explicitCwd){if(explicitCwd)return explicitCwd;if(entry2.dir)return entry2.dir;let repo=entry2.repo;if(repo&&__require("fs").existsSync(repo))return repo;return process.cwd()}async function buildSpawnParams2(name,team,options,agent,preassignedSessionId,agentTemplate){let resolvedProvider=options.provider??agent.entry.provider??"claude",params={provider:resolvedProvider,team,role:name,agentTemplate:agentTemplate??name,skill:options.skill,extraArgs:options.extraArgs,model:agent.model,systemPromptFile:agent.identityPath??void 0,promptMode:agent.entry.promptMode,initialPrompt:options.prompt??options.initialPrompt,newWindow:options.newWindow,windowTarget:options.window},isIdentitySpawn=options.role!==void 0&&options.role!==name,{parentSessionId,spawnColor,nativeTeam}=await resolveNativeTeam(team,agent.repoPath,{...options,provider:resolvedProvider,role:name,isIdentitySpawn});if(nativeTeam)params.nativeTeam=nativeTeam;try{let{injectTeamHooks:injectTeamHooks2}=await Promise.resolve().then(() => (init_inject(),exports_inject));if(await injectTeamHooks2(team))console.log(` Hooks: injected genie hook dispatch into team "${team}"`)}catch(err){console.warn(`Warning: could not inject hooks for team "${team}": ${err instanceof Error?err.message:err}`)}if(params.provider==="codex")try{let{injectCodexHooks:injectCodexHooks2}=await Promise.resolve().then(() => (init_codex_inject(),exports_codex_inject));if(await injectCodexHooks2())console.log(" Hooks: injected genie hook dispatch into ~/.codex/config.toml")}catch(err){console.warn(`Warning: could not inject codex hooks: ${err instanceof Error?err.message:err}`)}if(params.provider==="claude")params.sessionId=preassignedSessionId??crypto.randomUUID();if(params.provider==="claude"){if(await startOtelReceiver())params.otelPort=getOtelPort(),params.otelLogPrompts=!0}return{params,parentSessionId,spawnColor}}async function maybeStartOtelRelay(nt,validated,insideTmux){if(!nt?.enabled&&validated.provider==="codex"&&insideTmux)return ensureCodexOtelConfig(),await ensureOtelRelay(validated.team);return!1}function buildSdkRuntimeExtra(options){let extra={};if(options.sdkMaxTurns!=null)extra.maxTurns=options.sdkMaxTurns;if(options.sdkMaxBudget!=null)extra.maxBudgetUsd=options.sdkMaxBudget;if(options.sdkEffort)extra.effort=options.sdkEffort;if(options.sdkResume)extra.resume=options.sdkResume;return Object.keys(extra).length>0?extra:void 0}async function dispatchSpawn(ctx,validated,options,agent,insideTmux){if(validated.provider==="claude-sdk"){let streamFormat=options.streamFormat??"text",streamOpts=options.stream||options.sdkStream?{stream:!0,streamFormat}:void 0;return await launchSdkSpawn(ctx,agent.entry.permissions,streamOpts,agent.entry.sdk,buildSdkRuntimeExtra(options))}if(insideTmux)return await launchTmuxSpawn(ctx);return await launchInlineSpawn(ctx)}async function resolveTeamName3(opts){if(opts.explicitTeam)return opts.explicitTeam;if(opts.entryTeam)return opts.entryTeam;let env=opts.env??process.env;if(env.GENIE_TEAM)return env.GENIE_TEAM;return await(opts.discover??discoverTeamName)()??null}async function pickParallelShortId(baseName,team,uuid){if(!UUID_REGEX.test(uuid))throw Error(`pickParallelShortId: expected a well-formed UUID (8-4-4-4-12 hex), got ${JSON.stringify(uuid)}`);let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2();for(let k=4;k<=uuid.length;k++){let slice=uuid.slice(0,k),id=`${baseName}-${slice}`;if((await sql`
1989
1988
  SELECT id FROM agents WHERE id = ${id} LIMIT 1
1990
1989
  `).length===0)return slice}return uuid}async function resolveSpawnIdentity(name,team,uuidFactory=()=>crypto.randomUUID(),isAliveFn=(agent)=>resolveWorkerLivenessByTransport(agent)){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
1991
1990
  SELECT id, pane_id, team FROM agents WHERE id = ${name} LIMIT 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/genie",
3
- "version": "4.260428.13",
3
+ "version": "4.260428.14",
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.260428.13",
3
+ "version": "4.260428.14",
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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie-plugin",
3
- "version": "4.260428.13",
3
+ "version": "4.260428.14",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",