@automagik/genie 4.260428.7 → 4.260428.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/genie.js CHANGED
@@ -1093,10 +1093,10 @@ Run 'genie agent list' to list agents.`)}async function resolveTarget(target,opt
1093
1093
  `),recentLines=lines.slice(-linesToAnalyze).join(`
1094
1094
  `),cleanOutput=stripAnsi(recentLines),baseState={timestamp:Date.now(),rawOutput:recentLines},permissionMatch=getFirstMatch(cleanOutput,permissionPatterns);if(permissionMatch)return{...baseState,type:"permission",detail:permissionMatch.type.replace("_permission",""),confidence:0.9};let hasPlanApproval=hasMatch(cleanOutput,questionPatterns.filter((p)=>p.type==="claude_code_plan_approval")),cleanMenuLines=stripAnsi(lines.slice(-15).join(`
1095
1095
  `)),questionMatches=matchPatterns(cleanMenuLines,questionPatterns),questionState=detectQuestionState(questionMatches,hasPlanApproval,baseState);if(questionState)return questionState;let ynMatch=questionMatches.find((m)=>m.type==="yes_no_question");if(ynMatch)return{...baseState,type:"question",options:["Yes","No"],detail:`default: ${ynMatch.extracted?.default||"y"}`,confidence:0.85};let errorMatch=getFirstMatch(cleanOutput,errorPatterns);if(errorMatch)return{...baseState,type:"error",detail:errorMatch.extracted?.message||errorMatch.match[0],confidence:0.8};let toolMatch=getFirstMatch(cleanOutput,toolUsePatterns);if(toolMatch)return{...baseState,type:"tool_use",detail:`${toolMatch.type}: ${toolMatch.extracted?.command||toolMatch.extracted?.file||toolMatch.extracted?.query||""}`,confidence:0.75};if(hasMatch(cleanOutput,workingPatterns))return{...baseState,type:"working",confidence:0.7};if(hasMatch(cleanOutput,completionPatterns))return{...baseState,type:"complete",confidence:0.6};let cleanLastLines=stripAnsi(lines.slice(-5).join(`
1096
- `));if(hasMatch(cleanLastLines,idlePatterns))return{...baseState,type:"idle",confidence:0.7};let trimmedLast=cleanLastLines.trim();if(trimmedLast.endsWith(">")||trimmedLast.match(/>\s*$/))return{...baseState,type:"idle",detail:"prompt detected",confidence:0.65};return{...baseState,type:"unknown",confidence:minConfidence}}var init_state_detector=__esm(()=>{init_patterns()});var init_orchestrator=__esm(()=>{init_patterns();init_state_detector()});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_mailbox={};__export(exports_mailbox,{toNativeInboxMessage:()=>toNativeInboxMessage,subscribeDelivery:()=>subscribeDelivery,send:()=>send,readOutbox:()=>readOutbox,markRead:()=>markRead,markFailed:()=>markFailed,markEscalated:()=>markEscalated,markDelivered:()=>markDelivered,inbox:()=>inbox,getUnread:()=>getUnread,getRetryable:()=>getRetryable,getById:()=>getById});function generateMessageId(){return`msg-${v4_default()}`}function rowToMessage(row){return{id:row.id,from:row.from_worker,to:row.to_worker,body:row.body,createdAt:row.created_at instanceof Date?row.created_at.toISOString():String(row.created_at),read:row.read,deliveredAt:row.delivered_at?row.delivered_at instanceof Date?row.delivered_at.toISOString():String(row.delivered_at):null}}function normalizeWorkerIds(worker){let values2=Array.isArray(worker)?worker:[worker];return[...new Set(values2.map((value)=>value.trim()).filter(Boolean))]}async function send(repoPath,from,to,body){let sql=await getConnection(),id=generateMessageId(),now=new Date().toISOString(),span=isWideEmitEnabled()?startSpan("mailbox.delivery",{from,to,channel:"tmux",message_id:id},{source_subsystem:"mailbox",ctx:getAmbient()??void 0,repo_path:repoPath,agent:from}):null,outcome="queued";try{await sql`
1097
- INSERT INTO mailbox (id, from_worker, to_worker, body, repo_path, read, delivered_at, created_at)
1098
- VALUES (${id}, ${from}, ${to}, ${body}, ${repoPath}, false, ${null}, ${now})
1099
- `,outcome="queued"}catch(err){if(outcome="rejected",span)endSpan(span,{outcome:"rejected",body_excerpt:body.slice(0,256)},{source_subsystem:"mailbox",repo_path:repoPath,agent:from});throw err}let message={id,from,to,body,createdAt:now,read:!1,deliveredAt:null};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:message.id,from,to},source:"mailbox",timestamp:message.createdAt})}catch{}if(span)endSpan(span,{outcome,body_excerpt:body.slice(0,256),message_id:id},{source_subsystem:"mailbox",repo_path:repoPath,agent:from});return message}async function inbox(repoPath,workerId){let sql=await getConnection(),workerIds=normalizeWorkerIds(workerId);if(workerIds.length===0)return[];return(await sql`
1096
+ `));if(hasMatch(cleanLastLines,idlePatterns))return{...baseState,type:"idle",confidence:0.7};let trimmedLast=cleanLastLines.trim();if(trimmedLast.endsWith(">")||trimmedLast.match(/>\s*$/))return{...baseState,type:"idle",detail:"prompt detected",confidence:0.65};return{...baseState,type:"unknown",confidence:minConfidence}}var init_state_detector=__esm(()=>{init_patterns()});var init_orchestrator=__esm(()=>{init_patterns();init_state_detector()});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()});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=()=>{};var exports_mailbox={};__export(exports_mailbox,{toNativeInboxMessage:()=>toNativeInboxMessage,subscribeDelivery:()=>subscribeDelivery,send:()=>send,readOutbox:()=>readOutbox,markRead:()=>markRead,markFailed:()=>markFailed,markEscalated:()=>markEscalated,markDelivered:()=>markDelivered,inbox:()=>inbox,getUnread:()=>getUnread,getRetryable:()=>getRetryable,getById:()=>getById});function generateMessageId(){return`msg-${v4_default()}`}function rowToMessage(row){return{id:row.id,from:row.from_worker,to:row.to_worker,body:row.body,createdAt:row.created_at instanceof Date?row.created_at.toISOString():String(row.created_at),read:row.read,deliveredAt:row.delivered_at?row.delivered_at instanceof Date?row.delivered_at.toISOString():String(row.delivered_at):null,source:typeof row.source==="string"&&row.source.length>0?row.source:"agent",meta:row.meta&&typeof row.meta==="object"?row.meta:{}}}function normalizeWorkerIds(worker){let values2=Array.isArray(worker)?worker:[worker];return[...new Set(values2.map((value)=>value.trim()).filter(Boolean))]}async function send(repoPath,from,to,body,opts){let sql=await getConnection(),id=generateMessageId(),now=new Date().toISOString(),source=opts?.source&&opts.source.length>0?opts.source:"agent",meta=opts?.meta??{},span=isWideEmitEnabled()?startSpan("mailbox.delivery",{from,to,channel:"tmux",message_id:id},{source_subsystem:"mailbox",ctx:getAmbient()??void 0,repo_path:repoPath,agent:from}):null,outcome="queued";try{await sql`
1097
+ INSERT INTO mailbox (id, from_worker, to_worker, body, repo_path, read, delivered_at, created_at, source, meta)
1098
+ VALUES (${id}, ${from}, ${to}, ${body}, ${repoPath}, false, ${null}, ${now}, ${source}, ${sql.json(meta)})
1099
+ `,outcome="queued"}catch(err){if(outcome="rejected",span)endSpan(span,{outcome:"rejected",body_excerpt:body.slice(0,256)},{source_subsystem:"mailbox",repo_path:repoPath,agent:from});throw err}let message={id,from,to,body,createdAt:now,read:!1,deliveredAt:null,source,meta};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:message.id,from,to},source:"mailbox",timestamp:message.createdAt})}catch{}if(span)endSpan(span,{outcome,body_excerpt:body.slice(0,256),message_id:id},{source_subsystem:"mailbox",repo_path:repoPath,agent:from});return message}async function inbox(repoPath,workerId){let sql=await getConnection(),workerIds=normalizeWorkerIds(workerId);if(workerIds.length===0)return[];return(await sql`
1100
1100
  SELECT * FROM mailbox
1101
1101
  WHERE to_worker = ANY(${workerIds}) AND repo_path = ${repoPath}
1102
1102
  ORDER BY created_at ASC
@@ -1117,7 +1117,7 @@ Run 'genie agent list' to list agents.`)}async function resolveTarget(target,opt
1117
1117
  `;if(rows.length===0)return null;return rowToMessage(rows[0])}async function markRead(messageId){return(await(await getConnection())`
1118
1118
  UPDATE mailbox SET read = true WHERE id = ${messageId}
1119
1119
  RETURNING id
1120
- `).length>0}function toNativeInboxMessage(msg,color="blue"){let words=msg.body.split(/\s+/),summary=words.slice(0,8).join(" ")+(words.length>8?"...":"");return{from:msg.from,text:msg.body,summary,timestamp:msg.createdAt,color,read:!1}}async function markFailed(messageId){return(await(await getConnection())`
1120
+ `).length>0}function toNativeInboxMessage(msg,color="blue"){let words=msg.body.split(/\s+/),summary=words.slice(0,8).join(" ")+(words.length>8?"...":""),source=msg.source&&msg.source.length>0?msg.source:"agent";if(source==="agent")return{from:msg.from,text:msg.body,summary,timestamp:msg.createdAt,color,read:!1};let meta={};for(let[key,value]of Object.entries(msg.meta??{}))if(typeof value==="string"||typeof value==="number"||typeof value==="boolean")meta[key]=value;return{from:msg.from,text:formatEnvelope({source,from:msg.from,meta:msg.meta,body:msg.body}),summary,timestamp:msg.createdAt,color,read:!1,source,meta}}async function markFailed(messageId){return(await(await getConnection())`
1121
1121
  UPDATE mailbox
1122
1122
  SET delivery_status = 'failed',
1123
1123
  delivery_attempts = delivery_attempts + 1
@@ -1134,7 +1134,7 @@ Run 'genie agent list' to list agents.`)}async function resolveTarget(target,opt
1134
1134
  SET delivery_status = 'escalated'
1135
1135
  WHERE id = ${messageId}
1136
1136
  RETURNING id
1137
- `).length>0}async function subscribeDelivery(callback){let listener=await(await getConnection()).listen("genie_mailbox_delivery",(payload)=>{let[toWorker,messageId]=payload.split(":");if(toWorker&&messageId)callback(toWorker,messageId)});return async()=>{await listener.unlisten()}}var init_mailbox=__esm(()=>{init_dist_node();init_db();init_emit();init_trace_context()});var exports_brief={};__export(exports_brief,{generateBrief:()=>generateBrief,formatBrief:()=>formatBrief});async function resolveSince(options){if(options.since)return options.since;if(options.agent){let rows=await(await getConnection())`
1137
+ `).length>0}async function subscribeDelivery(callback){let listener=await(await getConnection()).listen("genie_mailbox_delivery",(payload)=>{let[toWorker,messageId]=payload.split(":");if(toWorker&&messageId)callback(toWorker,messageId)});return async()=>{await listener.unlisten()}}var init_mailbox=__esm(()=>{init_dist_node();init_channel_envelope();init_db();init_emit();init_trace_context()});var exports_brief={};__export(exports_brief,{generateBrief:()=>generateBrief,formatBrief:()=>formatBrief});async function resolveSince(options){if(options.since)return options.since;if(options.agent){let rows=await(await getConnection())`
1138
1138
  SELECT e.ended_at FROM executors e
1139
1139
  JOIN agents a ON e.agent_id = a.id
1140
1140
  WHERE a.custom_name = ${options.agent}
@@ -1985,7 +1985,7 @@ exec ${fullCommand}
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
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
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)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},{parentSessionId,spawnColor,nativeTeam}=await resolveNativeTeam(team,agent.repoPath,{...options,provider:resolvedProvider,role:name});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`
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`
1989
1989
  SELECT id FROM agents WHERE id = ${id} LIMIT 1
1990
1990
  `).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
1991
  SELECT id, pane_id, team FROM agents WHERE id = ${name} LIMIT 1
@@ -3795,7 +3795,7 @@ ${context}`}}}catch{return}}import{spawnSync as spawnSync3}from"child_process";v
3795
3795
  `);for(let line of lines){let match=line.match(/^\s*\u276F\s*(\d+)\./);if(match)return Number.parseInt(match[1],10)}return 1}async function navigateToOption(paneId,targetOption,currentOption){let diff=targetOption-currentOption,key=diff>0?"Down":"Up";for(let i2=0;i2<Math.abs(diff);i2++)await executeTmux2(`send-keys -t '${paneId}' ${key}`),await sleep2(50);await sleep2(100),await executeTmux2(`send-keys -t '${paneId}' Enter`)}async function answerQuestion(target,choice){try{let{paneId,label}=await resolveOrcTarget(target),output=await capturePaneContent(paneId,50),state=detectState(output);if(state.type!=="question"){console.log(`No question pending (state: ${state.type})`);return}if(choice.startsWith("text:")){let text=choice.slice(5);await sendTextChoice(paneId,text),console.log(`Sent feedback: "${text.substring(0,50)}${text.length>50?"...":""}"`)}else if(/^\d+$/.test(choice)){let targetOption=Number.parseInt(choice,10);await navigateToOption(paneId,targetOption,findCurrentOption(output)),console.log(`Selected option ${targetOption} for ${label}`)}else await executeTmux2(`send-keys -t '${paneId}' '${choice}'`),console.log(`Sent '${choice}' to ${label}`)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function shellEscape(str2){return`"${str2.replace(/"/g,"\\\"").replace(/\$/g,"\\$")}"`}function sleep2(ms){return new Promise((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(`
3796
3796
  (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(`
3797
3797
  No agents registered. Add one with: genie agent register <name> --dir <path>`),console.log(`Use --builtins to also see built-in roles and council members.
3798
- `);return}if(entries.length>0)printRegisteredAgentsTable(entries);if(includeBuiltins)printBuiltinAgentsTable()}function registerAgentDirectory(parent){parent.command("directory [name]").alias("dir").description("List all agents or show single entry details from directory").option("--json","Output as JSON").option("--builtins","Include built-in roles and council members").option("--all","Include archived agents").action(async(name,options)=>{try{if(name==="sync"){let resolved=await resolve5("sync");if(resolved&&!resolved.builtin)await showEntry("sync",options.json);else await handleSync()}else if(name)await showEntry(name,options.json);else await listEntries(options.json,options.builtins,options.all)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}async function handleSync(){let{findWorkspace:findWorkspace2}=await Promise.resolve().then(() => (init_workspace(),exports_workspace)),ws=findWorkspace2();if(!ws)console.error("Not in a genie workspace. Run `genie init` first."),process.exit(1);console.log(`Syncing agents from ${ws.root}/agents/...`);let result2=await syncAgentDirectory(ws.root);printSyncResult(result2)}init_emit();init_term_format();init_msg();var _taskService2;async function getTaskService2(){if(!_taskService2)_taskService2=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService2}function printConversation(conv,lastMsg){let name=conv.name??conv.id,type2=conv.type==="dm"?"DM":"Group",linked=conv.linkedEntity?` [${conv.linkedEntity}:${conv.linkedEntityId}]`:"",preview=lastMsg?truncate2(lastMsg.body,50):"(no messages)",time=lastMsg?formatTime(lastMsg.createdAt):"";if(console.log(` ${padRight(name,30)} ${padRight(type2,6)}${linked}`),lastMsg)console.log(` ${time} ${lastMsg.senderId}: ${preview}`);console.log("")}async function handleInbox2(agent,options){let ts3=await getTaskService2(),resolvedAgent=agent??await detectSenderIdentity(),actor={actorType:"local",actorId:resolvedAgent},conversations=await ts3.listConversations(actor);if(options.json){console.log(JSON.stringify(conversations,null,2));return}if(conversations.length===0){console.log(`No conversations for "${resolvedAgent}".`);return}console.log(""),console.log(`INBOX: ${resolvedAgent}`),console.log("\u2500".repeat(60));for(let conv of conversations){let messages2=await ts3.getMessages(conv.id,{limit:1}),lastMsg=messages2.length>0?messages2[messages2.length-1]:null;printConversation(conv,lastMsg)}}function registerAgentInbox(parent){let inbox2=parent.command("inbox").description("Inbox management \u2014 list messages or watch for new ones");inbox2.command("list [agent]",{isDefault:!0}).description("List conversations with recent messages").option("--json","Output as JSON").action(async(agent,options)=>{try{await handleInbox2(agent,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),inbox2.command("watch").description("Run inbox watcher in foreground (Ctrl+C to stop)").action(async()=>{let{checkInboxes:checkInboxes2,getInboxPollIntervalMs:getInboxPollIntervalMs2,startInboxWatcher:startInboxWatcher2,stopInboxWatcher:stopInboxWatcher2}=await Promise.resolve().then(() => (init_inbox_watcher(),exports_inbox_watcher)),pollMs=getInboxPollIntervalMs2();if(pollMs===0)console.log("Inbox watcher is disabled (GENIE_INBOX_POLL_MS=0)"),process.exit(0);console.log(`Inbox watcher starting (poll every ${pollMs/1000}s)`),console.log(`Press Ctrl+C to stop.
3798
+ `);return}if(entries.length>0)printRegisteredAgentsTable(entries);if(includeBuiltins)printBuiltinAgentsTable()}function registerAgentDirectory(parent){parent.command("directory [name]").alias("dir").description("List all agents or show single entry details from directory").option("--json","Output as JSON").option("--builtins","Include built-in roles and council members").option("--all","Include archived agents").action(async(name,options)=>{try{if(name==="sync"){let resolved=await resolve5("sync");if(resolved&&!resolved.builtin)await showEntry("sync",options.json);else await handleSync()}else if(name)await showEntry(name,options.json);else await listEntries(options.json,options.builtins,options.all)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}async function handleSync(){let{findWorkspace:findWorkspace2}=await Promise.resolve().then(() => (init_workspace(),exports_workspace)),ws=findWorkspace2();if(!ws)console.error("Not in a genie workspace. Run `genie init` first."),process.exit(1);console.log(`Syncing agents from ${ws.root}/agents/...`);let result2=await syncAgentDirectory(ws.root);printSyncResult(result2)}init_emit();init_term_format();init_msg();var _taskService2;async function getTaskService2(){if(!_taskService2)_taskService2=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService2}function extractSource(msg){if(!msg||typeof msg!=="object")return"agent";let meta=msg.metadata??{},value=typeof meta.source==="string"?meta.source:null;return value&&value.length>0?value:"agent"}function renderConversation(conv,lastMsg){let name=conv.name??conv.id,type2=conv.type==="dm"?"DM":"Group",linked=conv.linkedEntity?` [${conv.linkedEntity}:${conv.linkedEntityId}]`:"",preview=lastMsg?truncate2(lastMsg.body,50):"(no messages)",time=lastMsg?formatTime(lastMsg.createdAt):"",source=extractSource(lastMsg),sourceTag=source!=="agent"?`[${source}] `:"",lines=[` ${padRight(name,30)} ${padRight(type2,6)}${linked}`];if(lastMsg)lines.push(` ${sourceTag}${time} ${lastMsg.senderId}: ${preview}`);return lines.push(""),lines}function printConversation(conv,lastMsg){for(let line of renderConversation(conv,lastMsg))console.log(line)}function buildInboxEntry(conversation,lastMessage){let source=extractSource(lastMessage),meta=lastMessage?.metadata??{};return{conversation,lastMessage,source,meta}}async function handleInbox2(agent,options){let ts3=await getTaskService2(),resolvedAgent=agent??await detectSenderIdentity(),actor={actorType:"local",actorId:resolvedAgent},conversations=await ts3.listConversations(actor),enriched=await Promise.all(conversations.map(async(conv)=>{let messages2=await ts3.getMessages(conv.id,{limit:1}),lastMessage=messages2.length>0?messages2[messages2.length-1]:null;return buildInboxEntry(conv,lastMessage)}));if(options.json){console.log(JSON.stringify(enriched,null,2));return}if(enriched.length===0){console.log(`No conversations for "${resolvedAgent}".`);return}console.log(""),console.log(`INBOX: ${resolvedAgent}`),console.log("\u2500".repeat(60));for(let entry2 of enriched)printConversation(entry2.conversation,entry2.lastMessage)}function registerAgentInbox(parent){let inbox2=parent.command("inbox").description("Inbox management \u2014 list messages or watch for new ones");inbox2.command("list [agent]",{isDefault:!0}).description("List conversations with recent messages").option("--json","Output as JSON").action(async(agent,options)=>{try{await handleInbox2(agent,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),inbox2.command("watch").description("Run inbox watcher in foreground (Ctrl+C to stop)").action(async()=>{let{checkInboxes:checkInboxes2,getInboxPollIntervalMs:getInboxPollIntervalMs2,startInboxWatcher:startInboxWatcher2,stopInboxWatcher:stopInboxWatcher2}=await Promise.resolve().then(() => (init_inbox_watcher(),exports_inbox_watcher)),pollMs=getInboxPollIntervalMs2();if(pollMs===0)console.log("Inbox watcher is disabled (GENIE_INBOX_POLL_MS=0)"),process.exit(0);console.log(`Inbox watcher starting (poll every ${pollMs/1000}s)`),console.log(`Press Ctrl+C to stop.
3799
3799
  `);let initial=await checkInboxes2();if(initial.length>0)console.log(`[inbox-watcher] Spawned team-leads for: ${initial.join(", ")}`);let handle=startInboxWatcher2({listTeamsWithUnreadInbox:(await Promise.resolve().then(() => (init_claude_native_teams(),exports_claude_native_teams))).listTeamsWithUnreadInbox,isTeamActive:async(teamName)=>{let{isTeamActive:isTeamActive2}=await Promise.resolve().then(() => (init_team_auto_spawn(),exports_team_auto_spawn));return isTeamActive2(teamName)},isAgentAlive:async(agentName)=>{let{isAgentAlive:isAgentAlive2}=await Promise.resolve().then(() => (init_team_auto_spawn(),exports_team_auto_spawn));return isAgentAlive2(agentName)},ensureTeamLead:async(teamName,workingDir)=>{let{ensureTeamLead:ensureTeamLead2}=await Promise.resolve().then(() => (init_team_auto_spawn(),exports_team_auto_spawn)),result2=await ensureTeamLead2(teamName,workingDir);return console.log(`[inbox-watcher] Spawned team-lead for "${teamName}" in ${workingDir}`),result2},warn:(msg)=>console.log(msg),emitDeadInbox:(payload)=>{try{emitEvent("rot.inbox-watcher-spawn-loop.detected",payload)}catch{}}}),shutdown2=()=>{console.log(`
3800
3800
  Stopping inbox watcher...`),stopInboxWatcher2(handle),process.exit(0)};process.on("SIGINT",shutdown2),process.on("SIGTERM",shutdown2),await new Promise(()=>{})})}init_agents();function registerAgentKill(parent){parent.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)}})}init_agents();function registerAgentList(parent){parent.command("list").alias("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)}})}init_agent_registry();init_term_format();init_db();init_mailbox();init_runtime_events();init_db();function rowToMessage2(row){return{id:row.id,sender:row.sender,body:row.body,timestamp:row.created_at instanceof Date?row.created_at.toISOString():String(row.created_at)}}async function readMessages(repoPath,teamName,since){let sql=await getConnection();if(since)return(await sql`
3801
3801
  SELECT * FROM team_chat
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/genie",
3
- "version": "4.260428.7",
3
+ "version": "4.260428.9",
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.7",
3
+ "version": "4.260428.9",
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.7",
3
+ "version": "4.260428.9",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",
@@ -0,0 +1,28 @@
1
+ -- 054_mailbox_source_meta.sql
2
+ --
3
+ -- Foundation for the channel-shaped envelope (PR A in the channels-pivot
4
+ -- roadmap). The mailbox row gains two optional, idempotent columns so the
5
+ -- delivery layer can carry source attribution and arbitrary metadata
6
+ -- (whatsapp phone, telegram chat id, system nudge kind, …) end-to-end:
7
+ --
8
+ -- - `source TEXT NOT NULL DEFAULT 'agent'` — origin of the message. The
9
+ -- default keeps every pre-existing row (and every legacy `mailbox.send`
10
+ -- caller that doesn't pass an opts arg) reading as `'agent'`, which is
11
+ -- the back-compat behaviour the renderer expects (plain body, no
12
+ -- `<channel …>` wrap).
13
+ -- - `meta JSONB NOT NULL DEFAULT '{}'::jsonb` — free-form k/v map.
14
+ -- Persisted verbatim and re-hydrated by the inbox/outbox readers so
15
+ -- channel-aware UIs round-trip the data.
16
+ --
17
+ -- Indexes are deliberately omitted — every existing inbox/outbox query
18
+ -- already filters on `to_worker` / `from_worker`, so no extra index is
19
+ -- needed for the foundation. PR C+ may add a `(to_worker, source)` index
20
+ -- once it's clear which sources warrant their own hot path.
21
+ --
22
+ -- Re-runnable: both ALTER COLUMN clauses use `IF NOT EXISTS`.
23
+
24
+ ALTER TABLE mailbox
25
+ ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'agent';
26
+
27
+ ALTER TABLE mailbox
28
+ ADD COLUMN IF NOT EXISTS meta JSONB NOT NULL DEFAULT '{}'::jsonb;