@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
|
|
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.
|
|
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.
|
|
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"
|
|
@@ -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;
|