@automagik/genie 4.260421.10 → 4.260421.11

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
@@ -754,7 +754,7 @@ Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.
754
754
  UPDATE agents
755
755
  SET metadata = metadata || ${sql.json(metadataPatch)}
756
756
  WHERE role = ${name}
757
- `}catch{}return updated}function loadIdentity(entry2){if(!entry2.dir)return null;let agentsPath=join25(entry2.dir,"AGENTS.md");if(existsSync23(agentsPath))return agentsPath;return null}function builtinToEntry(agent){return{name:agent.name,dir:"",promptMode:agent.promptMode??"append",model:agent.model,roles:[],registeredAt:"(built-in)"}}function roleToEntry(role,team,metadata,createdAt){if(!(metadata&&Object.keys(metadata).length>0)){let builtin=[...BUILTIN_ROLES,...BUILTIN_COUNCIL_MEMBERS].find((b2)=>b2.name===role);if(builtin)return builtinToEntry(builtin)}let registeredAt=(typeof metadata?.registeredAt==="string"?metadata.registeredAt:void 0)??createdAt??"";return{name:role,dir:metadata?.dir||"",promptMode:metadata?.promptMode||"append",model:metadata?.model,roles:[],registeredAt,description:metadata?.description,color:metadata?.color,provider:metadata?.provider,permissions:metadata?.permissions,disallowedTools:metadata?.disallowedTools,omniScopes:metadata?.omniScopes,hooks:metadata?.hooks,sdk:metadata?.sdk,...metadata?.repo?{repo:metadata.repo}:team?{repo:team}:{}}}function buildMetadata(entry2){let meta={};if(entry2.dir)meta.dir=entry2.dir;if(entry2.repo)meta.repo=entry2.repo;if(entry2.model)meta.model=entry2.model;if(entry2.promptMode&&entry2.promptMode!=="append")meta.promptMode=entry2.promptMode;if(entry2.description)meta.description=entry2.description;if(entry2.color)meta.color=entry2.color;if(entry2.provider)meta.provider=entry2.provider;if(entry2.permissions)meta.permissions=entry2.permissions;if(entry2.disallowedTools)meta.disallowedTools=entry2.disallowedTools;if(entry2.omniScopes)meta.omniScopes=entry2.omniScopes;if(entry2.hooks)meta.hooks=entry2.hooks;if(entry2.sdk)meta.sdk=entry2.sdk;return meta}function parseMetadata(raw){if(!raw)return{};if(typeof raw==="object"&&!Array.isArray(raw))return raw;if(typeof raw==="string")try{return JSON.parse(raw)}catch{return{}}return{}}var init_agent_directory=__esm(()=>{init_builtin_agents()});var exports_runtime_events={};__export(exports_runtime_events,{waitForRuntimeEvent:()=>waitForRuntimeEvent,publishSubjectEvent:()=>publishSubjectEvent,publishRuntimeEvent:()=>publishRuntimeEvent,listRuntimeEvents:()=>listRuntimeEvents,getLatestRuntimeEventId:()=>getLatestRuntimeEventId,getEventMetrics:()=>getEventMetrics,followRuntimeEvents:()=>followRuntimeEvents});class EventCircuitBreaker{failures=0;lastFailure=0;loggedOpen=!1;threshold=5;cooldown=30000;isOpen(){if(this.failures<this.threshold)return!1;if(Date.now()-this.lastFailure>this.cooldown)return this.failures=0,!1;return!0}recordSuccess(){if(this.failures>=this.threshold)console.warn("[runtime-events] circuit breaker closed \u2014 PG writes resumed");this.failures=0,this.loggedOpen=!1}recordFailure(){if(this.failures++,this.lastFailure=Date.now(),this.failures>=this.threshold&&!this.loggedOpen)console.warn(`[runtime-events] circuit breaker open \u2014 skipping PG writes for ${this.cooldown/1000}s after ${this.threshold} consecutive failures`),this.loggedOpen=!0}get state(){if(this.failures<this.threshold)return"closed";if(Date.now()-this.lastFailure>this.cooldown)return"half-open";return"open"}}function getEventMetrics(){return{eventsEmitted,eventsFailed,lastEmitDuration,circuitState:circuitBreaker.state}}function logFollowDrainError(context,error2,active){if(!active)return;let message=error2 instanceof Error?error2.message:String(error2);console.error(`[runtime-events] ${context} drain failed: ${message}`)}function rowToRuntimeEvent(row){return{id:Number(row.id),repoPath:row.repo_path,timestamp:row.created_at instanceof Date?row.created_at.toISOString():String(row.created_at),kind:row.kind,agent:row.agent,team:row.team??void 0,direction:row.direction??void 0,peer:row.peer??void 0,text:row.text,data:row.data??void 0,source:row.source,subject:row.subject??void 0,threadId:row.thread_id??void 0,traceId:row.trace_id??void 0,parentEventId:row.parent_event_id!=null?Number(row.parent_event_id):void 0}}function nextParam(values2,value){return values2.push(value),`$${values2.length}`}function buildScopeClause(query,values2){let scopeClauses=[];if(query.agentIds&&query.agentIds.length>0)scopeClauses.push(`agent = ANY(${nextParam(values2,query.agentIds)})`);if(query.team)scopeClauses.push(`team = ${nextParam(values2,query.team)}`);if(query.teamPrefix)scopeClauses.push(`team LIKE ${nextParam(values2,`${query.teamPrefix}%`)}`);if(scopeClauses.length===0)return null;if(scopeClauses.length===1)return scopeClauses[0];if(query.scopeMode==="any")return`(${scopeClauses.join(" OR ")})`;return`(${scopeClauses.join(" AND ")})`}function buildWhere(query){let values2=[],clauses=[];if(query.afterId!=null)clauses.push(`id > ${nextParam(values2,query.afterId)}`);if(query.repoPath)clauses.push(`repo_path = ${nextParam(values2,query.repoPath)}`);if(query.subject)clauses.push(`subject = ${nextParam(values2,query.subject)}`);if(query.kinds&&query.kinds.length>0)clauses.push(`kind = ANY(${nextParam(values2,query.kinds)})`);if(query.since)clauses.push(`created_at >= ${nextParam(values2,query.since)}`);if(query.threadId)clauses.push(`thread_id = ${nextParam(values2,query.threadId)}`);if(query.traceId)clauses.push(`trace_id = ${nextParam(values2,query.traceId)}`);let scopeClause=buildScopeClause(query,values2);if(scopeClause)clauses.push(scopeClause);return{clause:clauses.length>0?`WHERE ${clauses.join(" AND ")}`:"",values:values2}}async function publishRuntimeEvent(input){if(circuitBreaker.isOpen())throw eventsFailed++,Error("circuit breaker open \u2014 PG event write skipped");let start=Date.now();try{let sql=await getConnection(),threadId=input.threadId??`agent:${input.agent}`,rows=await sql`
757
+ `}catch{}return updated}function loadIdentity(entry2){if(!entry2.dir)return null;let agentsPath=join25(entry2.dir,"AGENTS.md");if(existsSync23(agentsPath))return agentsPath;return null}function builtinToEntry(agent){return{name:agent.name,dir:"",promptMode:agent.promptMode??"append",model:agent.model,roles:[],registeredAt:"(built-in)"}}function roleToEntry(role,team,metadata,createdAt){if(!(metadata&&Object.keys(metadata).length>0)){let builtin=[...BUILTIN_ROLES,...BUILTIN_COUNCIL_MEMBERS].find((b2)=>b2.name===role);if(builtin)return builtinToEntry(builtin)}let registeredAt=(typeof metadata?.registeredAt==="string"?metadata.registeredAt:void 0)??createdAt??"";return{name:role,dir:metadata?.dir||"",promptMode:metadata?.promptMode||"append",model:metadata?.model,roles:[],registeredAt,description:metadata?.description,color:metadata?.color,provider:metadata?.provider,permissions:metadata?.permissions,disallowedTools:metadata?.disallowedTools,omniScopes:metadata?.omniScopes,hooks:metadata?.hooks,sdk:metadata?.sdk,...metadata?.repo?{repo:metadata.repo}:team?{repo:team}:{}}}function buildMetadata(entry2){let meta={};if(entry2.dir)meta.dir=entry2.dir;if(entry2.repo)meta.repo=entry2.repo;if(entry2.model)meta.model=entry2.model;if(entry2.promptMode&&entry2.promptMode!=="append")meta.promptMode=entry2.promptMode;if(entry2.description)meta.description=entry2.description;if(entry2.color)meta.color=entry2.color;if(entry2.provider)meta.provider=entry2.provider;if(entry2.permissions)meta.permissions=entry2.permissions;if(entry2.disallowedTools)meta.disallowedTools=entry2.disallowedTools;if(entry2.omniScopes)meta.omniScopes=entry2.omniScopes;if(entry2.hooks)meta.hooks=entry2.hooks;if(entry2.sdk)meta.sdk=entry2.sdk;return meta}function parseMetadata(raw){if(!raw)return{};if(typeof raw==="object"&&!Array.isArray(raw))return raw;if(typeof raw==="string")try{return JSON.parse(raw)}catch{return{}}return{}}var init_agent_directory=__esm(()=>{init_builtin_agents()});var exports_runtime_events={};__export(exports_runtime_events,{waitForRuntimeEvent:()=>waitForRuntimeEvent,queryRuntimeEventThroughput:()=>queryRuntimeEventThroughput,publishSubjectEvent:()=>publishSubjectEvent,publishRuntimeEvent:()=>publishRuntimeEvent,listRuntimeEvents:()=>listRuntimeEvents,getLatestRuntimeEventId:()=>getLatestRuntimeEventId,followRuntimeEvents:()=>followRuntimeEvents});class EventCircuitBreaker{failures=0;lastFailure=0;loggedOpen=!1;threshold=5;cooldown=30000;isOpen(){if(this.failures<this.threshold)return!1;if(Date.now()-this.lastFailure>this.cooldown)return this.failures=0,!1;return!0}recordSuccess(){if(this.failures>=this.threshold)console.warn("[runtime-events] circuit breaker closed \u2014 PG writes resumed");this.failures=0,this.loggedOpen=!1}recordFailure(){if(this.failures++,this.lastFailure=Date.now(),this.failures>=this.threshold&&!this.loggedOpen)console.warn(`[runtime-events] circuit breaker open \u2014 skipping PG writes for ${this.cooldown/1000}s after ${this.threshold} consecutive failures`),this.loggedOpen=!0}get state(){if(this.failures<this.threshold)return"closed";if(Date.now()-this.lastFailure>this.cooldown)return"half-open";return"open"}}function logFollowDrainError(context,error2,active){if(!active)return;let message=error2 instanceof Error?error2.message:String(error2);console.error(`[runtime-events] ${context} drain failed: ${message}`)}function rowToRuntimeEvent(row){return{id:Number(row.id),repoPath:row.repo_path,timestamp:row.created_at instanceof Date?row.created_at.toISOString():String(row.created_at),kind:row.kind,agent:row.agent,team:row.team??void 0,direction:row.direction??void 0,peer:row.peer??void 0,text:row.text,data:row.data??void 0,source:row.source,subject:row.subject??void 0,threadId:row.thread_id??void 0,traceId:row.trace_id??void 0,parentEventId:row.parent_event_id!=null?Number(row.parent_event_id):void 0}}function nextParam(values2,value){return values2.push(value),`$${values2.length}`}function buildScopeClause(query,values2){let scopeClauses=[];if(query.agentIds&&query.agentIds.length>0)scopeClauses.push(`agent = ANY(${nextParam(values2,query.agentIds)})`);if(query.team)scopeClauses.push(`team = ${nextParam(values2,query.team)}`);if(query.teamPrefix)scopeClauses.push(`team LIKE ${nextParam(values2,`${query.teamPrefix}%`)}`);if(scopeClauses.length===0)return null;if(scopeClauses.length===1)return scopeClauses[0];if(query.scopeMode==="any")return`(${scopeClauses.join(" OR ")})`;return`(${scopeClauses.join(" AND ")})`}function buildWhere(query){let values2=[],clauses=[];if(query.afterId!=null)clauses.push(`id > ${nextParam(values2,query.afterId)}`);if(query.repoPath)clauses.push(`repo_path = ${nextParam(values2,query.repoPath)}`);if(query.subject)clauses.push(`subject = ${nextParam(values2,query.subject)}`);if(query.kinds&&query.kinds.length>0)clauses.push(`kind = ANY(${nextParam(values2,query.kinds)})`);if(query.since)clauses.push(`created_at >= ${nextParam(values2,query.since)}`);if(query.threadId)clauses.push(`thread_id = ${nextParam(values2,query.threadId)}`);if(query.traceId)clauses.push(`trace_id = ${nextParam(values2,query.traceId)}`);let scopeClause=buildScopeClause(query,values2);if(scopeClause)clauses.push(scopeClause);return{clause:clauses.length>0?`WHERE ${clauses.join(" AND ")}`:"",values:values2}}async function publishRuntimeEvent(input){if(circuitBreaker.isOpen())throw Error("circuit breaker open \u2014 PG event write skipped");try{let sql=await getConnection(),threadId=input.threadId??`agent:${input.agent}`,rows=await sql`
758
758
  INSERT INTO genie_runtime_events (
759
759
  repo_path, subject, kind, source, agent, team, direction, peer, text, data, thread_id, trace_id, parent_event_id, created_at
760
760
  )
@@ -775,7 +775,11 @@ Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.
775
775
  ${input.timestamp??new Date().toISOString()}
776
776
  )
777
777
  RETURNING id, repo_path, subject, kind, source, agent, team, direction, peer, text, data, thread_id, trace_id, parent_event_id, created_at
778
- `;return circuitBreaker.recordSuccess(),eventsEmitted++,lastEmitDuration=Date.now()-start,rowToRuntimeEvent(rows[0])}catch(error2){throw circuitBreaker.recordFailure(),eventsFailed++,error2}}async function publishSubjectEvent(repoPath,subject,event){return publishRuntimeEvent({...event,repoPath,subject})}async function listRuntimeEvents(query={}){let sql=await getConnection(),{clause,values:values2}=buildWhere(query),limit=query.limit??500;return(await sql.unsafe(`
778
+ `;return circuitBreaker.recordSuccess(),rowToRuntimeEvent(rows[0])}catch(error2){throw circuitBreaker.recordFailure(),error2}}async function publishSubjectEvent(repoPath,subject,event){return publishRuntimeEvent({...event,repoPath,subject})}async function queryRuntimeEventThroughput(windowSeconds=60){if(!Number.isFinite(windowSeconds)||windowSeconds<=0)throw Error(`windowSeconds must be a positive number, got ${windowSeconds}`);return{emitted:(await(await getConnection())`
779
+ SELECT COUNT(*)::int AS emitted
780
+ FROM genie_runtime_events
781
+ WHERE created_at > NOW() - make_interval(secs => ${windowSeconds})
782
+ `)[0]?.emitted??0}}async function listRuntimeEvents(query={}){let sql=await getConnection(),{clause,values:values2}=buildWhere(query),limit=query.limit??500;return(await sql.unsafe(`
779
783
  SELECT id, repo_path, subject, kind, source, agent, team, direction, peer, text, data, thread_id, trace_id, parent_event_id, created_at
780
784
  FROM genie_runtime_events
781
785
  ${clause}
@@ -783,7 +787,7 @@ Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.
783
787
  LIMIT $${values2.length+1}
784
788
  `,[...values2,limit])).map(rowToRuntimeEvent)}async function getLatestRuntimeEventId(){let rows=await(await getConnection())`
785
789
  SELECT COALESCE(MAX(id), 0) AS max_id FROM genie_runtime_events
786
- `;return Number(rows[0]?.max_id??0)}async function followRuntimeEvents(query,onEvent,options){let sql=await getConnection(),active=!0,lastSeenId=query.afterId??await getLatestRuntimeEventId(),drainChain=Promise.resolve(),drain=async()=>{if(!active)return;let events=await listRuntimeEvents({...query,afterId:lastSeenId});for(let event of events)lastSeenId=event.id,onEvent(event)},queueDrain=(context)=>{drainChain=drainChain.then(drain).catch((error2)=>{logFollowDrainError(context,error2,active)})},listener=await sql.listen("genie_runtime_event",()=>{queueDrain("notify")});await drain();let pollIntervalMs=options?.pollIntervalMs??1000,pollTimer=setInterval(()=>{queueDrain("poll")},pollIntervalMs);return{mode:"pg",stop:async()=>{active=!1,clearInterval(pollTimer);try{await drainChain}catch{}try{await listener.unlisten()}catch{}}}}async function waitForRuntimeEvent(query,timeoutMs,predicate){let afterId=query.afterId??0;return new Promise((resolve5,reject)=>{let settled=!1,handle=null,timer2=null,finish=async(event)=>{if(settled)return;if(settled=!0,timer2)clearTimeout(timer2);try{if(handle)await handle.stop()}catch{}resolve5(event)};(async()=>{try{if(handle=await followRuntimeEvents({...query,afterId},(event)=>{if(predicate&&!predicate(event))return;finish(event)},{pollIntervalMs:250}),settled){try{await handle.stop()}catch{}return}timer2=setTimeout(()=>{finish(null)},timeoutMs)}catch(err){if(!settled)settled=!0,reject(err)}})()})}var circuitBreaker,eventsEmitted=0,eventsFailed=0,lastEmitDuration=0;var init_runtime_events=__esm(()=>{init_db();circuitBreaker=new EventCircuitBreaker});var exports_interactivity={};__export(exports_interactivity,{isInteractive:()=>isInteractive,installWorkspaceCheck:()=>installWorkspaceCheck,ensureWorkspace:()=>ensureWorkspace,commandRequiresWorkspace:()=>commandRequiresWorkspace});function isInteractive(){if(!process.stdout.isTTY)return!1;if(process.env.CI)return!1;if(process.argv.includes("--no-interactive"))return!1;return!0}function getRootCommandName(cmd){let current=cmd;while(current.parent?.parent)current=current.parent;return current.name()}function commandRequiresWorkspace(cmd){return!WORKSPACE_EXEMPT.has(getRootCommandName(cmd))}async function ensureWorkspace(){if(findWorkspace())return;if(!isInteractive())console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{confirm}=await Promise.resolve().then(() => (init_esm14(),exports_esm));if(!await confirm({message:"No workspace found. Initialize? [Y/n]",default:!0}))console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{mkdirSync:mkdirSync11,writeFileSync:writeFileSync10}=await import("fs"),{basename:basename5,join:join28}=await import("path"),cwd=process.cwd(),genieDir=join28(cwd,".genie");mkdirSync11(genieDir,{recursive:!0});let config={name:basename5(cwd),agents:{defaults:{}},tmux:{socket:"genie"},sdk:{}};writeFileSync10(join28(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
790
+ `;return Number(rows[0]?.max_id??0)}async function followRuntimeEvents(query,onEvent,options){let sql=await getConnection(),active=!0,lastSeenId=query.afterId??await getLatestRuntimeEventId(),drainChain=Promise.resolve(),drain=async()=>{if(!active)return;let events=await listRuntimeEvents({...query,afterId:lastSeenId});for(let event of events)lastSeenId=event.id,onEvent(event)},queueDrain=(context)=>{drainChain=drainChain.then(drain).catch((error2)=>{logFollowDrainError(context,error2,active)})},listener=await sql.listen("genie_runtime_event",()=>{queueDrain("notify")});await drain();let pollIntervalMs=options?.pollIntervalMs??1000,pollTimer=setInterval(()=>{queueDrain("poll")},pollIntervalMs);return{mode:"pg",stop:async()=>{active=!1,clearInterval(pollTimer);try{await drainChain}catch{}try{await listener.unlisten()}catch{}}}}async function waitForRuntimeEvent(query,timeoutMs,predicate){let afterId=query.afterId??0;return new Promise((resolve5,reject)=>{let settled=!1,handle=null,timer2=null,finish=async(event)=>{if(settled)return;if(settled=!0,timer2)clearTimeout(timer2);try{if(handle)await handle.stop()}catch{}resolve5(event)};(async()=>{try{if(handle=await followRuntimeEvents({...query,afterId},(event)=>{if(predicate&&!predicate(event))return;finish(event)},{pollIntervalMs:250}),settled){try{await handle.stop()}catch{}return}timer2=setTimeout(()=>{finish(null)},timeoutMs)}catch(err){if(!settled)settled=!0,reject(err)}})()})}var circuitBreaker;var init_runtime_events=__esm(()=>{init_db();circuitBreaker=new EventCircuitBreaker});var exports_interactivity={};__export(exports_interactivity,{isInteractive:()=>isInteractive,installWorkspaceCheck:()=>installWorkspaceCheck,ensureWorkspace:()=>ensureWorkspace,commandRequiresWorkspace:()=>commandRequiresWorkspace});function isInteractive(){if(!process.stdout.isTTY)return!1;if(process.env.CI)return!1;if(process.argv.includes("--no-interactive"))return!1;return!0}function getRootCommandName(cmd){let current=cmd;while(current.parent?.parent)current=current.parent;return current.name()}function commandRequiresWorkspace(cmd){return!WORKSPACE_EXEMPT.has(getRootCommandName(cmd))}async function ensureWorkspace(){if(findWorkspace())return;if(!isInteractive())console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{confirm}=await Promise.resolve().then(() => (init_esm14(),exports_esm));if(!await confirm({message:"No workspace found. Initialize? [Y/n]",default:!0}))console.error("No workspace found. Run `genie init` to set up."),process.exit(2);let{mkdirSync:mkdirSync11,writeFileSync:writeFileSync10}=await import("fs"),{basename:basename5,join:join28}=await import("path"),cwd=process.cwd(),genieDir=join28(cwd,".genie");mkdirSync11(genieDir,{recursive:!0});let config={name:basename5(cwd),agents:{defaults:{}},tmux:{socket:"genie"},sdk:{}};writeFileSync10(join28(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
787
791
  `),console.log(`Workspace initialized: ${cwd}`)}function installWorkspaceCheck(program2){program2.hook("preAction",async(_thisCommand,actionCommand)=>{if(!commandRequiresWorkspace(actionCommand))return;await ensureWorkspace()})}var WORKSPACE_EXEMPT;var init_interactivity=__esm(()=>{init_workspace();WORKSPACE_EXEMPT=new Set(["init","setup","doctor","update","uninstall","shortcuts","team","version","help"])});function extractValue(kv){let v=kv.value;if(v.stringValue!==void 0)return v.stringValue;if(v.intValue!==void 0)return typeof v.intValue==="string"?Number.parseInt(v.intValue,10):v.intValue;if(v.doubleValue!==void 0)return v.doubleValue;if(v.boolValue!==void 0)return v.boolValue;return}function attrsToObject(attrs){if(!attrs)return{};let obj={};for(let kv of attrs)obj[kv.key]=extractValue(kv);return obj}function extractResourceContext(resource){let attrs=attrsToObject(resource?.attributes);return{agentName:attrs["agent.name"],teamName:attrs["team.name"],wishSlug:attrs["wish.slug"],sessionId:attrs["session.id"],agentRole:attrs["agent.role"]}}function mapEventToEntityType(eventName){if(eventName.includes("tool_result"))return"otel_tool";if(eventName.includes("api_request")||eventName.includes("api_error"))return"otel_api";if(eventName.includes("user_prompt"))return"otel_prompt";if(eventName.includes("tool_decision"))return"otel_decision";return"otel_event"}function resolveEntityId(ctx){return ctx.sessionId??(ctx.agentName?`agent:${ctx.agentName}`:"unknown")}function mergeContext(details,ctx){if(ctx.teamName)details.team=ctx.teamName;if(ctx.wishSlug)details.wish_slug=ctx.wishSlug;if(ctx.agentRole)details.agent_role=ctx.agentRole;if(ctx.sessionId)details.session_id=ctx.sessionId}function logRecordToRow(record,ctx){let logAttrs=attrsToObject(record.attributes),eventName=logAttrs["event.name"]??record.body?.stringValue??"unknown",details={...logAttrs,event_name:eventName};if(mergeContext(details,ctx),record.severityText)details.severity=record.severityText;if(record.body?.kvlistValue?.values)Object.assign(details,attrsToObject(record.body.kvlistValue.values));return{entity_type:mapEventToEntityType(eventName),entity_id:resolveEntityId(ctx),event_type:eventName,actor:ctx.agentName??null,details}}function processLogs(payload){let rows=[];for(let resourceLog of payload.resourceLogs??[]){let ctx=extractResourceContext(resourceLog.resource);for(let scopeLog of resourceLog.scopeLogs??[])for(let record of scopeLog.logRecords??[])rows.push(logRecordToRow(record,ctx))}return rows}function buildMetricRow(metricName,entityId,actor,details){return{entity_type:"otel_metric",entity_id:entityId,event_type:metricName,actor,details}}function processSumGaugePoints(dataPoints,metricName,unit,entityId,ctx){return dataPoints.map((dp)=>{let dpAttrs=attrsToObject(dp.attributes),value=dp.asDouble??(dp.asInt!==void 0?Number(dp.asInt):void 0),details={metric_name:metricName,value,...dpAttrs};if(unit)details.unit=unit;return mergeContext(details,ctx),buildMetricRow(metricName,entityId,ctx.agentName??null,details)})}function metricToRows(metric,ctx){let metricName=metric.name??"unknown_metric",entityId=resolveEntityId(ctx),dataPoints=metric.sum?.dataPoints??metric.gauge?.dataPoints??[],rows=processSumGaugePoints(dataPoints,metricName,metric.unit,entityId,ctx);for(let dp of metric.histogram?.dataPoints??[]){let dpAttrs=attrsToObject(dp.attributes),details={metric_name:metricName,sum:dp.sum,count:dp.count!==void 0?Number(dp.count):void 0,...dpAttrs};if(metric.unit)details.unit=metric.unit;mergeContext(details,ctx),rows.push(buildMetricRow(metricName,entityId,ctx.agentName??null,details))}return rows}function processMetrics(payload){let rows=[];for(let resourceMetric of payload.resourceMetrics??[]){let ctx=extractResourceContext(resourceMetric.resource);for(let scopeMetric of resourceMetric.scopeMetrics??[])for(let metric of scopeMetric.metrics??[])rows.push(...metricToRows(metric,ctx))}return rows}async function flushToPg(rows){if(rows.length===0)return;try{let{getConnection:getConnection2,isAvailable:isAvailable2}=await Promise.resolve().then(() => (init_db(),exports_db));if(!await isAvailable2())return;let sql=await getConnection2();await sql`
788
792
  INSERT INTO audit_events (entity_type, entity_id, event_type, actor, details)
789
793
  SELECT * FROM unnest(
@@ -3899,8 +3903,8 @@ coverage
3899
3903
 
3900
3904
  _This file is maintained by the auto-memory system. New memories are added automatically._
3901
3905
  `);let reposTarget=join59(workspaceRoot,"repos");if(existsSync52(reposTarget))try{symlinkSync(reposTarget,join59(agentDir,"repos"))}catch{}if(console.log(`Agent scaffolded: agents/${name}/`),console.log(" AGENTS.md, SOUL.md, HEARTBEAT.md"),console.log(" brain/memory/MEMORY.md (seeded)"),console.log(" .claude/settings.local.json (auto-memory enabled)"),existsSync52(join59(agentDir,"repos")))console.log(" repos -> ../repos (symlink)")}async function maybeBootstrapDefaultAgent(workspaceRoot){if(scanAgents(workspaceRoot).length>0)return!1;if(!await esm_default4({message:"No agent found in this workspace. Scaffold the default `genie` agent now?",default:!0}))return console.log(" Skipped default agent bootstrap. Run `genie init agent genie` later."),!1;return scaffoldAgentInWorkspace(workspaceRoot,"genie"),!0}async function syncWorkspaceAgents(workspaceRoot){let agents=scanAgents(workspaceRoot);if(agents.length===0)return;console.log(` Found ${agents.length} agent(s): ${agents.join(", ")}`);try{let{syncAgentDirectory:syncAgentDirectory2}=await Promise.resolve().then(() => (init_agent_sync(),exports_agent_sync)),result2=await syncAgentDirectory2(workspaceRoot);if(result2.registered.length>0)console.log(` Registered: ${result2.registered.join(", ")}`);if(result2.updated.length>0)console.log(` Updated: ${result2.updated.join(", ")}`)}catch{}}async function initWorkspace(){let cwd=process.cwd(),existing=findWorkspace(cwd);if(existing){if(console.log(`Already inside workspace: ${existing.root}`),await maybeBootstrapDefaultAgent(existing.root))await syncWorkspaceAgents(existing.root);return}let genieDir=join59(cwd,".genie");mkdirSync23(genieDir,{recursive:!0});let pgUrl=detectPgUrl(),config={name:basename10(cwd),pgUrl,agents:{defaults:{}},tmux:{socket:"genie"},sdk:{}};writeFileSync25(join59(genieDir,"workspace.json"),`${JSON.stringify(config,null,2)}
3902
- `);let genieignorePath=join59(cwd,".genieignore");if(!existsSync52(genieignorePath))writeFileSync25(genieignorePath,GENIEIGNORE_DEFAULTS,"utf-8"),console.log(" Created .genieignore");if(console.log(`Workspace created: ${cwd}`),pgUrl)console.log(` pgUrl: ${pgUrl}`);await maybeBootstrapDefaultAgent(cwd),await syncWorkspaceAgents(cwd),await runPostInitFlow(cwd,config)}async function runPostInitFlow(workspaceRoot,config){if(!isInteractive())return;let discovered=await discoverExternalAgents(workspaceRoot);refreshPending(workspaceRoot,discovered);let pending=listPending(workspaceRoot),ctx={workspaceRoot,workspaceName:basename10(workspaceRoot),config,discovered,pending,canonicalAgentCount:scanAgents(workspaceRoot).length},result2=await runMiniWizard(ctx);if(result2.importedAgents.length>0){let toImport=pending.filter((p)=>result2.importedAgents.includes(p.name)),discoveredToImport=toImport.map((p)=>({name:p.name,path:p.path,relativePath:p.relativePath,isSubAgent:p.isSubAgent,parentName:p.parentName})),importResult=importAgents(workspaceRoot,discoveredToImport);for(let name of importResult.imported){let agent=toImport.find((a)=>a.name===name);if(agent)removePending(workspaceRoot,agent.path);console.log(` Imported: ${name}`)}for(let err of importResult.errors)console.error(` Import failed (${err.name}): ${err.error}`);await syncWorkspaceAgents(workspaceRoot)}}function resolveAgentsDir(wsRoot,dirOption){if(dirOption)return resolve9(dirOption);let cwd=process.cwd(),rel=relative4(wsRoot,cwd);if(rel.startsWith(".."))return join59(wsRoot,"agents");let segments=rel===""?[]:rel.split(sep2),idx=segments.indexOf("agents");if(idx===-1)return join59(wsRoot,"agents");return join59(wsRoot,...segments.slice(0,idx+1))}async function initAgent(name,options){if(!name||/[\/\\]/.test(name)||name==="."||name===".."||name.includes(".."))console.error("Error: Agent name must not contain path separators or traversal sequences."),process.exit(1);let cwd=process.cwd(),ws=findWorkspace(cwd);if(!ws)console.error("Error: Not in a genie workspace. Run `genie init` first."),process.exit(1);let agentsDir=resolveAgentsDir(ws.root,options.dir);try{scaffoldAgentInWorkspace(ws.root,name,agentsDir)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function registerInitCommands(program2){program2.command("init").description("Initialize a genie workspace").action(async()=>{await ensureSetupCompleteForInit(),await initWorkspace()}).command("agent <name>").description("Scaffold a new agent in the workspace").option("--dir <path>","Target directory for agent (default: CWD if inside agents/, else workspace agents/)").action(async(name,options)=>{await ensureSetupCompleteForInit(),await initAgent(name,options)})}init_db();init_runtime_events();init_term_format();function parseSince4(since){let match=since.match(/^(\d+)([smhd])$/);if(!match)return since;let amount=Number.parseInt(match[1],10),unit=match[2],ms={s:1000,m:60000,h:3600000,d:86400000}[unit]??3600000;return new Date(Date.now()-amount*ms).toISOString()}async function metricsNowCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),snapshots=await sql`SELECT * FROM machine_snapshots ORDER BY created_at DESC LIMIT 1`,agentCount=await sql`SELECT count(DISTINCT agent_id)::int as cnt FROM executors WHERE state NOT IN ('done', 'error', 'terminated')`,teamCount=await sql`SELECT count(*)::int as cnt FROM teams WHERE status = 'in_progress'`,snapshot=snapshots[0]??{},eventMetrics=getEventMetrics(),data={active_workers:snapshot.active_workers??agentCount[0]?.cnt??0,active_teams:snapshot.active_teams??teamCount[0]?.cnt??0,tmux_sessions:snapshot.tmux_sessions??0,cpu_percent:snapshot.cpu_percent??null,memory_mb:snapshot.memory_mb??null,snapshot_at:snapshot.created_at?new Date(snapshot.created_at).toISOString():null,events_emitted:eventMetrics.eventsEmitted,events_failed:eventMetrics.eventsFailed,last_emit_duration_ms:eventMetrics.lastEmitDuration,circuit_state:eventMetrics.circuitState};if(options.json){console.log(JSON.stringify(data,null,2));return}if(console.log("Machine State:"),console.log(` Workers: ${data.active_workers}`),console.log(` Teams: ${data.active_teams}`),console.log(` Tmux: ${data.tmux_sessions} sessions`),data.cpu_percent!==null)console.log(` CPU: ${data.cpu_percent}%`);if(data.memory_mb!==null)console.log(` Memory: ${data.memory_mb} MB`);if(data.snapshot_at)console.log(` As of: ${formatRelativeTimestamp(data.snapshot_at)}`);console.log(`
3903
- Event Throughput:`),console.log(` Emitted: ${data.events_emitted}`),console.log(` Failed: ${data.events_failed}`),console.log(` Last ms: ${data.last_emit_duration_ms}`),console.log(` Circuit: ${data.circuit_state}`)}async function metricsHistoryCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),sinceTs=parseSince4(options.since??"1h"),rows=await sql`
3906
+ `);let genieignorePath=join59(cwd,".genieignore");if(!existsSync52(genieignorePath))writeFileSync25(genieignorePath,GENIEIGNORE_DEFAULTS,"utf-8"),console.log(" Created .genieignore");if(console.log(`Workspace created: ${cwd}`),pgUrl)console.log(` pgUrl: ${pgUrl}`);await maybeBootstrapDefaultAgent(cwd),await syncWorkspaceAgents(cwd),await runPostInitFlow(cwd,config)}async function runPostInitFlow(workspaceRoot,config){if(!isInteractive())return;let discovered=await discoverExternalAgents(workspaceRoot);refreshPending(workspaceRoot,discovered);let pending=listPending(workspaceRoot),ctx={workspaceRoot,workspaceName:basename10(workspaceRoot),config,discovered,pending,canonicalAgentCount:scanAgents(workspaceRoot).length},result2=await runMiniWizard(ctx);if(result2.importedAgents.length>0){let toImport=pending.filter((p)=>result2.importedAgents.includes(p.name)),discoveredToImport=toImport.map((p)=>({name:p.name,path:p.path,relativePath:p.relativePath,isSubAgent:p.isSubAgent,parentName:p.parentName})),importResult=importAgents(workspaceRoot,discoveredToImport);for(let name of importResult.imported){let agent=toImport.find((a)=>a.name===name);if(agent)removePending(workspaceRoot,agent.path);console.log(` Imported: ${name}`)}for(let err of importResult.errors)console.error(` Import failed (${err.name}): ${err.error}`);await syncWorkspaceAgents(workspaceRoot)}}function resolveAgentsDir(wsRoot,dirOption){if(dirOption)return resolve9(dirOption);let cwd=process.cwd(),rel=relative4(wsRoot,cwd);if(rel.startsWith(".."))return join59(wsRoot,"agents");let segments=rel===""?[]:rel.split(sep2),idx=segments.indexOf("agents");if(idx===-1)return join59(wsRoot,"agents");return join59(wsRoot,...segments.slice(0,idx+1))}async function initAgent(name,options){if(!name||/[\/\\]/.test(name)||name==="."||name===".."||name.includes(".."))console.error("Error: Agent name must not contain path separators or traversal sequences."),process.exit(1);let cwd=process.cwd(),ws=findWorkspace(cwd);if(!ws)console.error("Error: Not in a genie workspace. Run `genie init` first."),process.exit(1);let agentsDir=resolveAgentsDir(ws.root,options.dir);try{scaffoldAgentInWorkspace(ws.root,name,agentsDir)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}function registerInitCommands(program2){program2.command("init").description("Initialize a genie workspace").action(async()=>{await ensureSetupCompleteForInit(),await initWorkspace()}).command("agent <name>").description("Scaffold a new agent in the workspace").option("--dir <path>","Target directory for agent (default: CWD if inside agents/, else workspace agents/)").action(async(name,options)=>{await ensureSetupCompleteForInit(),await initAgent(name,options)})}init_db();init_runtime_events();init_term_format();function parseSince4(since){let match=since.match(/^(\d+)([smhd])$/);if(!match)return since;let amount=Number.parseInt(match[1],10),unit=match[2],ms={s:1000,m:60000,h:3600000,d:86400000}[unit]??3600000;return new Date(Date.now()-amount*ms).toISOString()}async function metricsNowCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),snapshots=await sql`SELECT * FROM machine_snapshots ORDER BY created_at DESC LIMIT 1`,agentCount=await sql`SELECT count(DISTINCT agent_id)::int as cnt FROM executors WHERE state NOT IN ('done', 'error', 'terminated')`,teamCount=await sql`SELECT count(*)::int as cnt FROM teams WHERE status = 'in_progress'`,snapshot=snapshots[0]??{},throughput=await queryRuntimeEventThroughput(60),data={active_workers:snapshot.active_workers??agentCount[0]?.cnt??0,active_teams:snapshot.active_teams??teamCount[0]?.cnt??0,tmux_sessions:snapshot.tmux_sessions??0,cpu_percent:snapshot.cpu_percent??null,memory_mb:snapshot.memory_mb??null,snapshot_at:snapshot.created_at?new Date(snapshot.created_at).toISOString():null,events_emitted_last_60s:throughput.emitted};if(options.json){console.log(JSON.stringify(data,null,2));return}if(console.log("Machine State:"),console.log(` Workers: ${data.active_workers}`),console.log(` Teams: ${data.active_teams}`),console.log(` Tmux: ${data.tmux_sessions} sessions`),data.cpu_percent!==null)console.log(` CPU: ${data.cpu_percent}%`);if(data.memory_mb!==null)console.log(` Memory: ${data.memory_mb} MB`);if(data.snapshot_at)console.log(` As of: ${formatRelativeTimestamp(data.snapshot_at)}`);console.log(`
3907
+ Event Throughput (last 60s):`),console.log(` Emitted: ${data.events_emitted_last_60s}`)}async function metricsHistoryCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),sinceTs=parseSince4(options.since??"1h"),rows=await sql`
3904
3908
  SELECT active_workers, active_teams, tmux_sessions, cpu_percent, memory_mb, created_at
3905
3909
  FROM machine_snapshots
3906
3910
  WHERE created_at >= ${sinceTs}::timestamptz
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/genie",
3
- "version": "4.260421.10",
3
+ "version": "4.260421.11",
4
4
  "description": "Collaborative terminal toolkit for human + AI workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie",
3
- "version": "4.260421.10",
3
+ "version": "4.260421.11",
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.260421.10",
3
+ "version": "4.260421.11",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",