@automagik/genie 4.260418.6 → 4.260418.7
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
|
@@ -608,12 +608,12 @@ ${body}`;writeFileSync9(filePath,output,"utf-8")}function serializeSdkConfig(sdk
|
|
|
608
608
|
INSERT INTO agents (id, role, custom_name, started_at, metadata)
|
|
609
609
|
VALUES (${`dir:${entry.name}`}, ${entry.name}, ${entry.name}, now(), ${sql.json(metadata)})
|
|
610
610
|
ON CONFLICT (id) DO UPDATE SET metadata = ${sql.json(metadata)}
|
|
611
|
-
`,full}async function rm3(name,
|
|
612
|
-
SELECT role, metadata FROM agents
|
|
611
|
+
`,full}async function rm3(name,options){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2(),dirRemoved=(await sql`DELETE FROM agents WHERE id = ${`dir:${name}`}`).count>0;if(options?.force){let roleDelete=await sql`DELETE FROM agents WHERE role = ${name}`;return{removed:dirRemoved||roleDelete.count>0}}if(dirRemoved)return{removed:!0};let instances=await sql`SELECT id FROM agents WHERE role = ${name}`;if(instances.length===0)return{removed:!1};let idList=instances.map((r)=>r.id).join(", ");return{removed:!1,message:`No directory entry for "${name}". Active instances: ${idList}. Use 'genie kill <id>' to terminate, or re-run with --force to remove all.`}}async function resolve3(name){let templateTeam=await lookupTemplateTeam(name);try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
|
|
612
|
+
SELECT role, metadata, created_at FROM agents
|
|
613
613
|
WHERE role = ${name}
|
|
614
614
|
ORDER BY (CASE WHEN id LIKE 'dir:%' THEN 0 ELSE 1 END), started_at DESC
|
|
615
615
|
LIMIT 1
|
|
616
|
-
`;if(rows.length>0){let meta=parseMetadata(rows[0].metadata),entry=roleToEntry(name,void 0,meta);if(templateTeam)entry.team=templateTeam;return{entry,builtin:!1}}}catch{}let builtinRole=BUILTIN_ROLES.find((r)=>r.name===name);if(builtinRole){let entry=builtinToEntry(builtinRole);if(templateTeam)entry.team=templateTeam;return{entry,builtin:!0}}let councilMember=BUILTIN_COUNCIL_MEMBERS.find((m)=>m.name===name);if(councilMember){let entry=builtinToEntry(councilMember);if(templateTeam)entry.team=templateTeam;return{entry,builtin:!0}}return null}async function lookupTemplateTeam(name){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`SELECT team FROM agent_templates WHERE id = ${name} LIMIT 1`;if(rows.length===0)return null;let team=rows[0].team;return typeof team==="string"&&team.length>0?team:null}catch{return null}}async function findSessionByRepo(repoPath){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
|
|
616
|
+
`;if(rows.length>0){let meta=parseMetadata(rows[0].metadata),createdAt=rows[0].created_at instanceof Date?rows[0].created_at.toISOString():rows[0].created_at,entry=roleToEntry(name,void 0,meta,createdAt);if(templateTeam)entry.team=templateTeam;return{entry,builtin:!1}}}catch{}let builtinRole=BUILTIN_ROLES.find((r)=>r.name===name);if(builtinRole){let entry=builtinToEntry(builtinRole);if(templateTeam)entry.team=templateTeam;return{entry,builtin:!0}}let councilMember=BUILTIN_COUNCIL_MEMBERS.find((m)=>m.name===name);if(councilMember){let entry=builtinToEntry(councilMember);if(templateTeam)entry.team=templateTeam;return{entry,builtin:!0}}return null}async function lookupTemplateTeam(name){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`SELECT team FROM agent_templates WHERE id = ${name} LIMIT 1`;if(rows.length===0)return null;let team=rows[0].team;return typeof team==="string"&&team.length>0?team:null}catch{return null}}async function findSessionByRepo(repoPath){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
|
|
617
617
|
SELECT session FROM agents
|
|
618
618
|
WHERE repo_path = ${repoPath}
|
|
619
619
|
AND session IS NOT NULL
|
|
@@ -622,12 +622,12 @@ ${body}`;writeFileSync9(filePath,output,"utf-8")}function serializeSdkConfig(sdk
|
|
|
622
622
|
ORDER BY started_at DESC
|
|
623
623
|
LIMIT 1
|
|
624
624
|
`;return rows.length>0?rows[0].session:null}catch{return null}}async function ls(){let result2=[],seen=new Set;try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
|
|
625
|
-
SELECT DISTINCT ON (a.role) a.role, a.team, a.metadata, e.repo_path, e.provider
|
|
625
|
+
SELECT DISTINCT ON (a.role) a.role, a.team, a.metadata, a.created_at, e.repo_path, e.provider
|
|
626
626
|
FROM agents a
|
|
627
627
|
LEFT JOIN executors e ON a.current_executor_id = e.id
|
|
628
628
|
WHERE a.role IS NOT NULL
|
|
629
629
|
ORDER BY a.role, (CASE WHEN a.id LIKE 'dir:%' THEN 0 ELSE 1 END), a.started_at DESC
|
|
630
|
-
`;for(let row of rows){let name=row.role;if(!seen.has(name)){let meta=parseMetadata(row.metadata),entry=roleToEntry(name,row.team,meta),repoPath=row.repo_path;if(repoPath)entry.dir=repoPath,entry.repo=repoPath;result2.push({...entry,scope:"global"}),seen.add(name)}}}catch{}return result2}async function get2(name,_options){return(await resolve3(name))?.entry??null}async function edit(name,updates,_options){if(updates.dir){if(!existsSync19(updates.dir))throw Error(`Directory does not exist: ${updates.dir}`);let agentsPath=join21(updates.dir,"AGENTS.md");if(!existsSync19(agentsPath))throw Error(`AGENTS.md not found in ${updates.dir}.`)}let existing=await get2(name);if(!existing)throw Error(`Agent "${name}" not found in directory.`);let updated=Object.assign(existing,updates),metadataPatch=buildMetadata(updated);try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2();if((await sql`
|
|
630
|
+
`;for(let row of rows){let name=row.role;if(!seen.has(name)){let meta=parseMetadata(row.metadata),createdAt=row.created_at instanceof Date?row.created_at.toISOString():row.created_at,entry=roleToEntry(name,row.team,meta,createdAt),repoPath=row.repo_path;if(repoPath)entry.dir=repoPath,entry.repo=repoPath;result2.push({...entry,scope:"global"}),seen.add(name)}}}catch{}return result2}async function get2(name,_options){return(await resolve3(name))?.entry??null}async function edit(name,updates,_options){if(updates.dir){if(!existsSync19(updates.dir))throw Error(`Directory does not exist: ${updates.dir}`);let agentsPath=join21(updates.dir,"AGENTS.md");if(!existsSync19(agentsPath))throw Error(`AGENTS.md not found in ${updates.dir}.`)}let existing=await get2(name);if(!existing)throw Error(`Agent "${name}" not found in directory.`);let updated=Object.assign(existing,updates),metadataPatch=buildMetadata(updated);try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2();if((await sql`
|
|
631
631
|
UPDATE agents
|
|
632
632
|
SET metadata = metadata || ${sql.json(metadataPatch)}
|
|
633
633
|
WHERE id = ${`dir:${name}`}
|
|
@@ -635,7 +635,7 @@ ${body}`;writeFileSync9(filePath,output,"utf-8")}function serializeSdkConfig(sdk
|
|
|
635
635
|
UPDATE agents
|
|
636
636
|
SET metadata = metadata || ${sql.json(metadataPatch)}
|
|
637
637
|
WHERE role = ${name}
|
|
638
|
-
`}catch{}return updated}function loadIdentity(entry){if(!entry.dir)return null;let agentsPath=join21(entry.dir,"AGENTS.md");if(existsSync19(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){if(!(metadata&&Object.keys(metadata).length>0)){let builtin=[...BUILTIN_ROLES,...BUILTIN_COUNCIL_MEMBERS].find((b2)=>b2.name===role);if(builtin)return builtinToEntry(builtin)}return{name:role,dir:metadata?.dir||"",promptMode:metadata?.promptMode||"append",model:metadata?.model,roles:[],registeredAt
|
|
638
|
+
`}catch{}return updated}function loadIdentity(entry){if(!entry.dir)return null;let agentsPath=join21(entry.dir,"AGENTS.md");if(existsSync19(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(entry){let meta={};if(entry.dir)meta.dir=entry.dir;if(entry.repo)meta.repo=entry.repo;if(entry.model)meta.model=entry.model;if(entry.promptMode&&entry.promptMode!=="append")meta.promptMode=entry.promptMode;if(entry.description)meta.description=entry.description;if(entry.color)meta.color=entry.color;if(entry.provider)meta.provider=entry.provider;if(entry.permissions)meta.permissions=entry.permissions;if(entry.disallowedTools)meta.disallowedTools=entry.disallowedTools;if(entry.omniScopes)meta.omniScopes=entry.omniScopes;if(entry.hooks)meta.hooks=entry.hooks;if(entry.sdk)meta.sdk=entry.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{}}function syncFrontmatterToDisk(entry,updates){try{if(!entry.dir)return;let agentsPath=join21(entry.dir,"AGENTS.md");if(!existsSync19(agentsPath))return;if(!Object.keys(updates).some((k)=>FRONTMATTER_KEYS.has(k)))return;let fmUpdates={};if(updates.model!==void 0)fmUpdates.model=updates.model;if(updates.description!==void 0)fmUpdates.description=updates.description;if(updates.color!==void 0)fmUpdates.color=updates.color;if(updates.promptMode!==void 0)fmUpdates.promptMode=updates.promptMode;if(updates.provider!==void 0)fmUpdates.provider=updates.provider;if(updates.sdk!==void 0)fmUpdates.sdk=serializeSdkConfig(updates.sdk);if(Object.keys(fmUpdates).length===0)return;writeFrontmatter(agentsPath,fmUpdates)}catch{}}var FRONTMATTER_KEYS;var init_agent_directory=__esm(()=>{init_builtin_agents();init_frontmatter_writer();FRONTMATTER_KEYS=new Set(["name","description","model","color","promptMode","provider","sdk"])});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`
|
|
639
639
|
INSERT INTO genie_runtime_events (
|
|
640
640
|
repo_path, subject, kind, source, agent, team, direction, peer, text, data, thread_id, trace_id, parent_event_id, created_at
|
|
641
641
|
)
|
|
@@ -767,7 +767,7 @@ Run 'genie agent list' to list agents.`)}async function resolveTarget(target,opt
|
|
|
767
767
|
LIMIT 100
|
|
768
768
|
`).map((r)=>({id:r.id,requestType:r.request_type,senderId:r.sender_id,body:r.body,createdAt:r.created_at instanceof Date?r.created_at.toISOString():String(r.created_at)}))}async function generateBrief(options){let teamConfig=await getTeam(options.team);if(!teamConfig)throw Error(`Team not found: ${options.team}`);let since=await resolveSince(options),repoPath=options.repoPath??teamConfig.repo,agentName=options.agent??teamConfig.leader??null,agentIdentifiers=agentName?[agentName]:[],[unreadMessages,taskMessages,recentEvents,pendingRequests,teamRoster]=await Promise.all([agentIdentifiers.length>0?getUnread(repoPath,agentIdentifiers):Promise.resolve([]),getTaskMessages(options.team,since),listRuntimeEvents({team:options.team,since,limit:100}),getPendingRequestMessages(options.team),getTeamRoster(options.team)]);return{team:options.team,agent:agentName,since,unreadMessages,taskMessages,recentEvents,pendingRequests,teamRoster}}function truncate(text,max){return text.length>max?`${text.slice(0,max)}...`:text}function formatUnreadSection(messages2){if(messages2.length===0)return[];let lines=[`## Unread Messages (${messages2.length})`];for(let msg of messages2)lines.push(`- **${msg.from}**: ${truncate(msg.body,120)}`);return lines.push(""),lines}function formatTaskMessagesSection(messages2){if(messages2.length===0)return[];let lines=[`## Task Updates (${messages2.length})`],byTask=new Map;for(let msg of messages2){let existing=byTask.get(msg.taskId)??[];existing.push(msg),byTask.set(msg.taskId,existing)}for(let[taskId,msgs]of byTask){lines.push(`### ${taskId}: ${msgs[0].taskTitle}`);for(let msg of msgs)lines.push(`- [${msg.senderType}:${msg.senderId}] ${truncate(msg.body,100)}`)}return lines.push(""),lines}function formatRequestsSection(requests){if(requests.length===0)return[];let lines=[`## Pending Requests (${requests.length})`];for(let req of requests)lines.push(`- [${req.requestType}] ${req.senderId}: ${truncate(req.body,80)}`);return lines.push(""),lines}function formatRosterSection(roster){if(roster.length===0)return[];let lines=[`## Team Roster (${roster.length})`];for(let member of roster){let state=member.executorState??"offline",icon=STATE_ICONS[state]??"\u25CC";lines.push(`- ${icon} **${member.agentId}** (${member.role??"unassigned"}): ${state}`)}return lines.push(""),lines}function formatEventsSection(events){if(events.length===0)return[];let lines=[`## Recent Events (${events.length})`],tail=events.slice(-10);for(let evt of tail){let ts3=evt.timestamp.slice(11,16);lines.push(`- ${ts3} [${evt.kind}] ${evt.agent}: ${truncate(evt.text,80)}`)}if(events.length>10)lines.push(` _(${events.length-10} more events)_`);return lines.push(""),lines}function formatBrief(brief){let lines=[`# BRIEF \u2014 ${brief.team}${brief.agent?` ${brief.agent}`:""}`,`Since: ${brief.since}`,"",...formatUnreadSection(brief.unreadMessages),...formatTaskMessagesSection(brief.taskMessages),...formatRequestsSection(brief.pendingRequests),...formatRosterSection(brief.teamRoster),...formatEventsSection(brief.recentEvents)];if(!(brief.unreadMessages.length+brief.taskMessages.length+brief.pendingRequests.length+brief.recentEvents.length>0))lines.push("_No activity since last session._","");return lines.join(`
|
|
769
769
|
`)}var STATE_ICONS;var init_brief=__esm(()=>{init_db();init_mailbox();init_runtime_events();init_team_manager();STATE_ICONS={working:"\u25CF",idle:"\u25CB",error:"\u2718"}});var exports_agent_sync={};__export(exports_agent_sync,{watchAgentDirectory:()=>watchAgentDirectory,syncAgentDirectory:()=>syncAgentDirectory,printSyncResult:()=>printSyncResult,healAgentFile:()=>healAgentFile});import{execSync as execSync6}from"child_process";import{existsSync as existsSync23,watch as fsWatch,readFileSync as readFileSync15,readdirSync as readdirSync6,realpathSync as realpathSync3,writeFileSync as writeFileSync11}from"fs";import{join as join25}from"path";function getGitRemoteUrl(dir){try{return execSync6(`git -C "${dir}" config --get remote.origin.url`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function extractOrgRepo(remoteUrl){let sshMatch=remoteUrl.match(/[^/:]+\/[^/]+?(?:\.git)?$/);if(sshMatch)return sshMatch[0].replace(/\.git$/,"");return null}function getRepoPathForAgent(agentDir){let reposLink=join25(agentDir,"repos");try{if(!existsSync23(reposLink))return null;let target=realpathSync3(reposLink);if(!existsSync23(target))return null;return target}catch{return null}}function discoverAgents(workspaceRoot){let agentsDir=join25(workspaceRoot,"agents");if(!existsSync23(agentsDir))return[];let agents=[];try{let entries=readdirSync6(agentsDir,{withFileTypes:!0});for(let entry of entries){if(!entry.isDirectory())continue;let agentDir=join25(agentsDir,entry.name);if(!existsSync23(join25(agentDir,"AGENTS.md")))continue;agents.push({name:entry.name,dir:agentDir,repoUrl:getGitRemoteUrl(agentDir),productRepo:getRepoPathForAgent(agentDir)}),discoverSubAgents(agentDir,entry.name,agents)}}catch{}return agents}function discoverSubAgents(parentDir,parentName,agents){let subAgentsDir=join25(parentDir,".genie","agents");if(!existsSync23(subAgentsDir))return;try{let entries=readdirSync6(subAgentsDir,{withFileTypes:!0});for(let entry of entries){if(!entry.isDirectory())continue;let subDir=join25(subAgentsDir,entry.name);if(!existsSync23(join25(subDir,"AGENTS.md")))continue;agents.push({name:`${parentName}/${entry.name}`,dir:subDir,repoUrl:getGitRemoteUrl(parentDir),productRepo:getRepoPathForAgent(parentDir)})}}catch{}}function discoverSingleAgent(workspaceRoot,agentName){let agentDir=join25(workspaceRoot,"agents",agentName);if(!existsSync23(join25(agentDir,"AGENTS.md")))return null;return{name:agentName,dir:agentDir,repoUrl:getGitRemoteUrl(agentDir),productRepo:getRepoPathForAgent(agentDir)}}function healAgentFile(agentsMdPath,agentName,healResult){let content=readFileSync15(agentsMdPath,"utf-8"),fmMatch=content.match(/^(---\n)([\s\S]*?)(\n---)/);if(!fmMatch)return!1;let prefix=fmMatch[1],fmBlock=fmMatch[2],suffix=fmMatch[3],rest=content.slice(fmMatch[0].length),modified=!1,healedBlock=fmBlock;for(let{field,value}of INVALID_LITERALS)if(new RegExp(`^${field}:\\s*${value}\\s*$`,"m").test(healedBlock))healedBlock=healedBlock.replace(new RegExp(`${field}:\\s*${value}\\s*\\n?`,"m"),""),healResult.healed.push({agent:agentName,field,value}),modified=!0;if(!modified)return!1;let newContent=prefix+healedBlock+suffix+rest,tmpPath=`${agentsMdPath}.tmp.${Date.now()}`;writeFileSync11(tmpPath,newContent,"utf-8");let{renameSync:renameSync2}=__require("fs");return renameSync2(tmpPath,agentsMdPath),!0}function buildResolveContext(workspaceRoot,agentName){let workspaceDefaults;try{workspaceDefaults=getWorkspaceConfig(workspaceRoot).agents?.defaults}catch{}let parent;if(agentName.includes("/")){let parentName=agentName.split("/")[0],parentAgentsMd=join25(workspaceRoot,"agents",parentName,"AGENTS.md");if(existsSync23(parentAgentsMd)){let parentContent=readFileSync15(parentAgentsMd,"utf-8"),parentFm=parseFrontmatter(parentContent);parent={name:parentName,fields:parentFm}}}return{workspaceDefaults,parent}}function computeResolvedMetadata(fm,ctx){let declared={},resolved={};for(let field of Object.keys(BUILTIN_DEFAULTS)){let fmValue=fm[field];if(fmValue!==void 0&&fmValue!==null&&fmValue!==""&&fmValue!=="inherit")declared[field]=fmValue;let result2=resolveFieldWithSource(fm,field,ctx);resolved[field]={value:result2.value,source:result2.source}}return{declared,resolved}}async function syncAgentDirectory(workspaceRoot){let result2={registered:[],updated:[],unchanged:[],archived:[],reactivated:[],healed:[],errors:[]},agents=discoverAgents(workspaceRoot),discoveredNames=new Set(agents.map((a)=>a.name)),healResult={healed:[]};for(let agent of agents){let agentsMdPath=join25(agent.dir,"AGENTS.md");try{healAgentFile(agentsMdPath,agent.name,healResult)}catch{}}result2.healed=healResult.healed;for(let h of healResult.healed)console.log(`[sync] healed ${h.agent}/AGENTS.md: removed invalid '${h.field}: ${h.value}' line`);for(let agent of agents)try{await syncSingleAgent(agent,result2,workspaceRoot)}catch(err){result2.errors.push({name:agent.name,error:err instanceof Error?err.message:String(err)})}return await removeMissingAgents(discoveredNames,result2),result2}function printSyncResult(result2){if(result2.healed.length>0)console.log(` Healed: ${result2.healed.length} invalid literal(s) removed`);if(result2.registered.length>0)console.log(` Registered: ${result2.registered.join(", ")}`);if(result2.updated.length>0)console.log(` Updated: ${result2.updated.join(", ")}`);if(result2.reactivated.length>0)console.log(` Reactivated: ${result2.reactivated.join(", ")}`);if(result2.archived.length>0)console.log(` Removed: ${result2.archived.join(", ")}`);if(result2.unchanged.length>0)console.log(` Unchanged: ${result2.unchanged.join(", ")}`);for(let err of result2.errors)console.error(` Error (${err.name}): ${err.error}`);let total=result2.registered.length+result2.updated.length+result2.unchanged.length+result2.reactivated.length;console.log(`
|
|
770
|
-
Sync complete: ${total} active agent(s), ${result2.archived.length} removed.`)}async function removeMissingAgents(discoveredNames,result2){try{let entries=await ls();for(let entry of entries){if(discoveredNames.has(entry.name))continue;if(entry.scope==="built-in")continue;if(!entry.dir||!entry.dir.includes("/agents/"))continue;if(await rm3(entry.name))result2.archived.push(entry.name)}}catch{}}async function syncSingleAgent(agent,result2,workspaceRoot){let repoPath=(agent.repoUrl?extractOrgRepo(agent.repoUrl):null)??agent.repoUrl??agent.dir,agentsMdPath=join25(agent.dir,"AGENTS.md"),content=readFileSync15(agentsMdPath,"utf-8"),fm=parseFrontmatter(content),_resolvedMeta;if(workspaceRoot){let ctx=buildResolveContext(workspaceRoot,agent.name);_resolvedMeta=computeResolvedMetadata(fm,ctx)}let resolved=await resolve3(agent.name),existing=resolved&&!resolved.builtin?resolved.entry:null,sdkConfig=fm.sdk,permissions=fm.permissions,disallowedTools=fm.disallowedTools,omniScopes=fm.omniScopes,hooks=fm.hooks;if(!existing){await add({name:agent.name,dir:agent.dir,repo:repoPath,promptMode:fm.promptMode??"append",model:fm.model,description:fm.description,color:fm.color,provider:fm.provider,permissions,disallowedTools,omniScopes,hooks,sdk:sdkConfig}),result2.registered.push(agent.name);return}let identityUpdate={dir:agent.dir,repo:repoPath,promptMode:fm.promptMode??"append",model:fm.model,description:fm.description,color:fm.color,provider:fm.provider,permissions,disallowedTools,omniScopes,hooks,sdk:sdkConfig},sdkChanged=JSON.stringify(existing.sdk)!==JSON.stringify(sdkConfig),permissionsChanged=JSON.stringify(existing.permissions)!==JSON.stringify(permissions),disallowedToolsChanged=JSON.stringify(existing.disallowedTools)!==JSON.stringify(disallowedTools),omniScopesChanged=JSON.stringify(existing.omniScopes)!==JSON.stringify(omniScopes),hooksChanged=JSON.stringify(existing.hooks)!==JSON.stringify(hooks);if(sdkChanged||permissionsChanged||disallowedToolsChanged||omniScopesChanged||hooksChanged||existing.repo!==repoPath||existing.dir!==agent.dir||existing.promptMode!==(fm.promptMode??"append")||existing.model!==fm.model||existing.description!==fm.description||existing.color!==fm.color||existing.provider!==fm.provider)await edit(agent.name,identityUpdate),result2.updated.push(agent.name);else result2.unchanged.push(agent.name)}async function syncSingleAgentByName(workspaceRoot,agentName){let agent=discoverSingleAgent(workspaceRoot,agentName);if(!agent)return"not-found";let result2={registered:[],updated:[],unchanged:[],archived:[],reactivated:[],healed:[],errors:[]};if(await syncSingleAgent(agent,result2,workspaceRoot),result2.registered.length>0)return"registered";if(result2.updated.length>0)return"updated";return"unchanged"}function watchAgentDirectory(workspaceRoot,options){let agentsDir=join25(workspaceRoot,"agents");if(!existsSync23(agentsDir))return null;let debounceTimer=null,pendingChanges=new Set,processChanges=async()=>{let names=[...pendingChanges];pendingChanges.clear();for(let name of names)try{let action=await processWatchedAgent(workspaceRoot,agentsDir,name);if(action)options?.onSync?.(name,action)}catch{}},watcher=fsWatch(agentsDir,{persistent:!1},(_event,filename)=>{if(!filename)return;let name=filename.split("/")[0];if(!name||name.startsWith("."))return;if(pendingChanges.add(name),debounceTimer)clearTimeout(debounceTimer);debounceTimer=setTimeout(processChanges,2000)});return{close:()=>{if(debounceTimer)clearTimeout(debounceTimer);watcher.close()}}}async function processWatchedAgent(workspaceRoot,agentsDir,name){let agentDir=join25(agentsDir,name);if(existsSync23(agentDir)&&existsSync23(join25(agentDir,"AGENTS.md"))){let action=await syncSingleAgentByName(workspaceRoot,name);return action!=="unchanged"&&action!=="not-found"?action:null}if(!existsSync23(agentDir)){if(await rm3(name))return"removed"}return null}var INVALID_LITERALS;var init_agent_sync=__esm(()=>{init_agent_directory();init_defaults();init_frontmatter();init_workspace();INVALID_LITERALS=[{field:"model",value:"inherit"}]});var exports_term_format={};__export(exports_term_format,{truncate:()=>truncate2,stripAnsi:()=>stripAnsi2,padRight:()=>padRight,formatTimestamp:()=>formatTimestamp,formatTime:()=>formatTime,formatRelativeTimestamp:()=>formatRelativeTimestamp,formatDate:()=>formatDate,color:()=>color});function padRight(str2,len){return str2.length>=len?str2:str2+" ".repeat(len-str2.length)}function truncate2(str2,len){return str2.length<=len?str2:`${str2.slice(0,len-1)}\u2026`}function formatDate(iso){if(!iso)return"-";return new Date(iso).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function formatRelativeTimestamp(ts3){let d=new Date(ts3),diffMs=Date.now()-d.getTime();if(diffMs<60000)return`${Math.floor(diffMs/1000)}s ago`;if(diffMs<3600000)return`${Math.floor(diffMs/60000)}m ago`;if(diffMs<86400000)return`${Math.floor(diffMs/3600000)}h ago`;return d.toISOString().replace("T"," ").slice(0,19)}function formatTimestamp(iso,opts){if(!iso)return opts?.fallback??"-";let d=iso instanceof Date?iso:new Date(iso),fmt={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1};if(opts?.seconds)fmt.second="2-digit";return d.toLocaleString("en-US",fmt)}function formatTime(iso,opts){try{let date=new Date(iso),fmt={hour:"2-digit",minute:"2-digit",hour12:!1};if(opts?.seconds)fmt.second="2-digit";return date.toLocaleTimeString("en-US",fmt)}catch{return opts?.fallback??"??:??"}}function color(name,text){return isTTY?`${ANSI[name]}${text}${ANSI.reset}`:text}function stripAnsi2(str2){return str2.replace(ANSI_REGEX,"")}var ANSI,isTTY,ANSI_REGEX;var init_term_format=__esm(()=>{ANSI={reset:"\x1B[0m",dim:"\x1B[2m",bold:"\x1B[1m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",gray:"\x1B[90m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightCyan:"\x1B[96m"},isTTY=process.stdout.isTTY&&!process.env.NO_COLOR;ANSI_REGEX=/\x1b\[[0-9;]*m/g});var exports_task_service={};__export(exports_task_service,{updateTask:()=>updateTask,updateMessage:()=>updateMessage,untagTask:()=>untagTask,unblockTask:()=>unblockTask,unarchiveTask:()=>unarchiveTask,unarchiveProject:()=>unarchiveProject,tagTask:()=>tagTask,setRelease:()=>setRelease,setPreference:()=>setPreference,sendMessage:()=>sendMessage,resolveTaskId:()=>resolveTaskId,resolveChannels:()=>resolveChannels,removeMember:()=>removeMember,removeDependency:()=>removeDependency,removeActor:()=>removeActor,releaseTask:()=>releaseTask,moveTask:()=>moveTask,markDone:()=>markDone,listTypes:()=>listTypes,listTasksForActor:()=>listTasksForActor,listTasks:()=>listTasks,listTags:()=>listTags,listReleases:()=>listReleases,listProjectsFiltered:()=>listProjectsFiltered,listProjects:()=>listProjects,listConversations:()=>listConversations,linkTask:()=>linkTask,getType:()=>getType,getTaskTags:()=>getTaskTags,getTaskActors:()=>getTaskActors,getTask:()=>getTask,getStageLog:()=>getStageLog,getProjectByRepoPath:()=>getProjectByRepoPath,getProjectByName:()=>getProjectByName,getPreferences:()=>getPreferences,getMessages:()=>getMessages,getMessage:()=>getMessage,getMembers:()=>getMembers,getDependents:()=>getDependents,getConversation:()=>getConversation,getCheckoutOwner:()=>getCheckoutOwner,getBlockingDependencies:()=>getBlockingDependencies,getBlockers:()=>getBlockers,forceUnlockTask:()=>forceUnlockTask,findOrCreateConversation:()=>findOrCreateConversation,expireStaleCheckouts:()=>expireStaleCheckouts,ensureProject:()=>ensureProject,deletePreference:()=>deletePreference,createType:()=>createType,createTask:()=>createTask,createTag:()=>createTag,createProject:()=>createProject,commentOnTask:()=>commentOnTask,checkoutTask:()=>checkoutTask,blockTask:()=>blockTask,assignTask:()=>assignTask,archiveTask:()=>archiveTask,archiveProject:()=>archiveProject,archiveBoard:()=>archiveBoard,addMember:()=>addMember,addDependency:()=>addDependency});import{execSync as execSync7}from"child_process";function str2(v){return v!=null?String(v):null}function strOrDefault(v,def){return v!=null?String(v):def}function mapTask(row){return{id:row.id,seq:row.seq,parentId:str2(row.parent_id),repoPath:row.repo_path,projectId:str2(row.project_id),genieOsFolderId:str2(row.genie_os_folder_id),wishFile:str2(row.wish_file),groupName:str2(row.group_name),title:row.title,description:str2(row.description),acceptanceCriteria:str2(row.acceptance_criteria),typeId:row.type_id,stage:row.stage,status:row.status,priority:row.priority,startDate:str2(row.start_date),dueDate:str2(row.due_date),estimatedEffort:str2(row.estimated_effort),startedAt:str2(row.started_at),endedAt:str2(row.ended_at),blockedReason:str2(row.blocked_reason),releaseId:str2(row.release_id),checkoutRunId:str2(row.checkout_run_id),executionLockedAt:str2(row.execution_locked_at),checkoutTimeoutMs:row.checkout_timeout_ms??600000,sessionId:str2(row.session_id),paneId:str2(row.pane_id),traceId:str2(row.trace_id),boardId:str2(row.board_id),columnId:str2(row.column_id),externalId:str2(row.external_id),externalUrl:str2(row.external_url),archivedAt:str2(row.archived_at),metadata:row.metadata??{},createdAt:strOrDefault(row.created_at,""),updatedAt:strOrDefault(row.updated_at,"")}}function mapConversation(row){return{id:row.id,parentMessageId:row.parent_message_id!=null?Number(row.parent_message_id):null,name:row.name??null,type:row.type,linkedEntity:row.linked_entity??null,linkedEntityId:row.linked_entity_id??null,createdByType:row.created_by_type??null,createdById:row.created_by_id??null,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapMessage(row){return{id:Number(row.id),conversationId:row.conversation_id,replyToId:row.reply_to_id!=null?Number(row.reply_to_id):null,senderType:row.sender_type,senderId:row.sender_id,body:row.body,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapTaskActor(row){return{taskId:row.task_id,actorType:row.actor_type,actorId:row.actor_id,role:row.role,permissions:row.permissions??{},createdAt:String(row.created_at)}}function mapDependency(row){return{taskId:row.task_id,dependsOnId:row.depends_on_id,depType:row.dep_type,createdAt:String(row.created_at)}}function mapTag(row){return{id:row.id,name:row.name,color:row.color??"#9ca3af",typeId:row.type_id??null,createdAt:String(row.created_at)}}function mapTaskType(row){return{id:row.id,name:row.name,description:row.description??null,icon:row.icon??null,stages:row.stages,isBuiltin:row.is_builtin,createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapNotificationPref(row){return{actorType:row.actor_type,actorId:row.actor_id,channel:row.channel,priorityThreshold:row.priority_threshold,isDefault:row.is_default,enabled:row.enabled,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapStageLog(row){return{id:Number(row.id),taskId:row.task_id,fromStage:row.from_stage??null,toStage:row.to_stage,actorType:row.actor_type??null,actorId:row.actor_id??null,runId:row.run_id??null,gateType:row.gate_type??null,createdAt:String(row.created_at)}}function mapConversationMember(row){return{conversationId:row.conversation_id,actorType:row.actor_type,actorId:row.actor_id,role:row.role,joinedAt:String(row.joined_at)}}function mapProject(row){return{id:row.id,name:row.name,repoPath:str2(row.repo_path),description:str2(row.description),leaderAgent:str2(row.leader_agent),tmuxSession:str2(row.tmux_session),status:strOrDefault(row.status,"active"),archivedAt:str2(row.archived_at),createdAt:String(row.created_at)}}function getRepoPath(){try{return execSync7("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}async function resolveTaskId(idOrSeq,repoPath){let sql=await getConnection(),repo=repoPath??getRepoPath(),projectSeqMatch=idOrSeq.match(/^([^#]+)#(\d+)$/);if(projectSeqMatch&&!idOrSeq.startsWith("#")){let[,projectName,seqStr]=projectSeqMatch,seq2=Number.parseInt(seqStr,10);if(Number.isNaN(seq2))return null;let rows2=await sql`
|
|
770
|
+
Sync complete: ${total} active agent(s), ${result2.archived.length} removed.`)}async function removeMissingAgents(discoveredNames,result2){try{let entries=await ls();for(let entry of entries){if(discoveredNames.has(entry.name))continue;if(entry.scope==="built-in")continue;if(!entry.dir||!entry.dir.includes("/agents/"))continue;let{removed}=await rm3(entry.name);if(removed)result2.archived.push(entry.name)}}catch{}}async function syncSingleAgent(agent,result2,workspaceRoot){let repoPath=(agent.repoUrl?extractOrgRepo(agent.repoUrl):null)??agent.repoUrl??agent.dir,agentsMdPath=join25(agent.dir,"AGENTS.md"),content=readFileSync15(agentsMdPath,"utf-8"),fm=parseFrontmatter(content),_resolvedMeta;if(workspaceRoot){let ctx=buildResolveContext(workspaceRoot,agent.name);_resolvedMeta=computeResolvedMetadata(fm,ctx)}let resolved=await resolve3(agent.name),existing=resolved&&!resolved.builtin?resolved.entry:null,sdkConfig=fm.sdk,permissions=fm.permissions,disallowedTools=fm.disallowedTools,omniScopes=fm.omniScopes,hooks=fm.hooks;if(!existing){await add({name:agent.name,dir:agent.dir,repo:repoPath,promptMode:fm.promptMode??"append",model:fm.model,description:fm.description,color:fm.color,provider:fm.provider,permissions,disallowedTools,omniScopes,hooks,sdk:sdkConfig}),result2.registered.push(agent.name);return}let identityUpdate={dir:agent.dir,repo:repoPath,promptMode:fm.promptMode??"append",model:fm.model,description:fm.description,color:fm.color,provider:fm.provider,permissions,disallowedTools,omniScopes,hooks,sdk:sdkConfig},sdkChanged=JSON.stringify(existing.sdk)!==JSON.stringify(sdkConfig),permissionsChanged=JSON.stringify(existing.permissions)!==JSON.stringify(permissions),disallowedToolsChanged=JSON.stringify(existing.disallowedTools)!==JSON.stringify(disallowedTools),omniScopesChanged=JSON.stringify(existing.omniScopes)!==JSON.stringify(omniScopes),hooksChanged=JSON.stringify(existing.hooks)!==JSON.stringify(hooks);if(sdkChanged||permissionsChanged||disallowedToolsChanged||omniScopesChanged||hooksChanged||existing.repo!==repoPath||existing.dir!==agent.dir||existing.promptMode!==(fm.promptMode??"append")||existing.model!==fm.model||existing.description!==fm.description||existing.color!==fm.color||existing.provider!==fm.provider)await edit(agent.name,identityUpdate),result2.updated.push(agent.name);else result2.unchanged.push(agent.name)}async function syncSingleAgentByName(workspaceRoot,agentName){let agent=discoverSingleAgent(workspaceRoot,agentName);if(!agent)return"not-found";let result2={registered:[],updated:[],unchanged:[],archived:[],reactivated:[],healed:[],errors:[]};if(await syncSingleAgent(agent,result2,workspaceRoot),result2.registered.length>0)return"registered";if(result2.updated.length>0)return"updated";return"unchanged"}function watchAgentDirectory(workspaceRoot,options){let agentsDir=join25(workspaceRoot,"agents");if(!existsSync23(agentsDir))return null;let debounceTimer=null,pendingChanges=new Set,processChanges=async()=>{let names=[...pendingChanges];pendingChanges.clear();for(let name of names)try{let action=await processWatchedAgent(workspaceRoot,agentsDir,name);if(action)options?.onSync?.(name,action)}catch{}},watcher=fsWatch(agentsDir,{persistent:!1},(_event,filename)=>{if(!filename)return;let name=filename.split("/")[0];if(!name||name.startsWith("."))return;if(pendingChanges.add(name),debounceTimer)clearTimeout(debounceTimer);debounceTimer=setTimeout(processChanges,2000)});return{close:()=>{if(debounceTimer)clearTimeout(debounceTimer);watcher.close()}}}async function processWatchedAgent(workspaceRoot,agentsDir,name){let agentDir=join25(agentsDir,name);if(existsSync23(agentDir)&&existsSync23(join25(agentDir,"AGENTS.md"))){let action=await syncSingleAgentByName(workspaceRoot,name);return action!=="unchanged"&&action!=="not-found"?action:null}if(!existsSync23(agentDir)){let{removed}=await rm3(name);if(removed)return"removed"}return null}var INVALID_LITERALS;var init_agent_sync=__esm(()=>{init_agent_directory();init_defaults();init_frontmatter();init_workspace();INVALID_LITERALS=[{field:"model",value:"inherit"}]});var exports_term_format={};__export(exports_term_format,{truncate:()=>truncate2,stripAnsi:()=>stripAnsi2,padRight:()=>padRight,formatTimestamp:()=>formatTimestamp,formatTime:()=>formatTime,formatRelativeTimestamp:()=>formatRelativeTimestamp,formatDate:()=>formatDate,color:()=>color});function padRight(str2,len){return str2.length>=len?str2:str2+" ".repeat(len-str2.length)}function truncate2(str2,len){return str2.length<=len?str2:`${str2.slice(0,len-1)}\u2026`}function formatDate(iso){if(!iso)return"-";return new Date(iso).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function formatRelativeTimestamp(ts3){let d=new Date(ts3),diffMs=Date.now()-d.getTime();if(diffMs<60000)return`${Math.floor(diffMs/1000)}s ago`;if(diffMs<3600000)return`${Math.floor(diffMs/60000)}m ago`;if(diffMs<86400000)return`${Math.floor(diffMs/3600000)}h ago`;return d.toISOString().replace("T"," ").slice(0,19)}function formatTimestamp(iso,opts){if(!iso)return opts?.fallback??"-";let d=iso instanceof Date?iso:new Date(iso),fmt={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1};if(opts?.seconds)fmt.second="2-digit";return d.toLocaleString("en-US",fmt)}function formatTime(iso,opts){try{let date=new Date(iso),fmt={hour:"2-digit",minute:"2-digit",hour12:!1};if(opts?.seconds)fmt.second="2-digit";return date.toLocaleTimeString("en-US",fmt)}catch{return opts?.fallback??"??:??"}}function color(name,text){return isTTY?`${ANSI[name]}${text}${ANSI.reset}`:text}function stripAnsi2(str2){return str2.replace(ANSI_REGEX,"")}var ANSI,isTTY,ANSI_REGEX;var init_term_format=__esm(()=>{ANSI={reset:"\x1B[0m",dim:"\x1B[2m",bold:"\x1B[1m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",gray:"\x1B[90m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightCyan:"\x1B[96m"},isTTY=process.stdout.isTTY&&!process.env.NO_COLOR;ANSI_REGEX=/\x1b\[[0-9;]*m/g});var exports_task_service={};__export(exports_task_service,{updateTask:()=>updateTask,updateMessage:()=>updateMessage,untagTask:()=>untagTask,unblockTask:()=>unblockTask,unarchiveTask:()=>unarchiveTask,unarchiveProject:()=>unarchiveProject,tagTask:()=>tagTask,setRelease:()=>setRelease,setPreference:()=>setPreference,sendMessage:()=>sendMessage,resolveTaskId:()=>resolveTaskId,resolveChannels:()=>resolveChannels,removeMember:()=>removeMember,removeDependency:()=>removeDependency,removeActor:()=>removeActor,releaseTask:()=>releaseTask,moveTask:()=>moveTask,markDone:()=>markDone,listTypes:()=>listTypes,listTasksForActor:()=>listTasksForActor,listTasks:()=>listTasks,listTags:()=>listTags,listReleases:()=>listReleases,listProjectsFiltered:()=>listProjectsFiltered,listProjects:()=>listProjects,listConversations:()=>listConversations,linkTask:()=>linkTask,getType:()=>getType,getTaskTags:()=>getTaskTags,getTaskActors:()=>getTaskActors,getTask:()=>getTask,getStageLog:()=>getStageLog,getProjectByRepoPath:()=>getProjectByRepoPath,getProjectByName:()=>getProjectByName,getPreferences:()=>getPreferences,getMessages:()=>getMessages,getMessage:()=>getMessage,getMembers:()=>getMembers,getDependents:()=>getDependents,getConversation:()=>getConversation,getCheckoutOwner:()=>getCheckoutOwner,getBlockingDependencies:()=>getBlockingDependencies,getBlockers:()=>getBlockers,forceUnlockTask:()=>forceUnlockTask,findOrCreateConversation:()=>findOrCreateConversation,expireStaleCheckouts:()=>expireStaleCheckouts,ensureProject:()=>ensureProject,deletePreference:()=>deletePreference,createType:()=>createType,createTask:()=>createTask,createTag:()=>createTag,createProject:()=>createProject,commentOnTask:()=>commentOnTask,checkoutTask:()=>checkoutTask,blockTask:()=>blockTask,assignTask:()=>assignTask,archiveTask:()=>archiveTask,archiveProject:()=>archiveProject,archiveBoard:()=>archiveBoard,addMember:()=>addMember,addDependency:()=>addDependency});import{execSync as execSync7}from"child_process";function str2(v){return v!=null?String(v):null}function strOrDefault(v,def){return v!=null?String(v):def}function mapTask(row){return{id:row.id,seq:row.seq,parentId:str2(row.parent_id),repoPath:row.repo_path,projectId:str2(row.project_id),genieOsFolderId:str2(row.genie_os_folder_id),wishFile:str2(row.wish_file),groupName:str2(row.group_name),title:row.title,description:str2(row.description),acceptanceCriteria:str2(row.acceptance_criteria),typeId:row.type_id,stage:row.stage,status:row.status,priority:row.priority,startDate:str2(row.start_date),dueDate:str2(row.due_date),estimatedEffort:str2(row.estimated_effort),startedAt:str2(row.started_at),endedAt:str2(row.ended_at),blockedReason:str2(row.blocked_reason),releaseId:str2(row.release_id),checkoutRunId:str2(row.checkout_run_id),executionLockedAt:str2(row.execution_locked_at),checkoutTimeoutMs:row.checkout_timeout_ms??600000,sessionId:str2(row.session_id),paneId:str2(row.pane_id),traceId:str2(row.trace_id),boardId:str2(row.board_id),columnId:str2(row.column_id),externalId:str2(row.external_id),externalUrl:str2(row.external_url),archivedAt:str2(row.archived_at),metadata:row.metadata??{},createdAt:strOrDefault(row.created_at,""),updatedAt:strOrDefault(row.updated_at,"")}}function mapConversation(row){return{id:row.id,parentMessageId:row.parent_message_id!=null?Number(row.parent_message_id):null,name:row.name??null,type:row.type,linkedEntity:row.linked_entity??null,linkedEntityId:row.linked_entity_id??null,createdByType:row.created_by_type??null,createdById:row.created_by_id??null,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapMessage(row){return{id:Number(row.id),conversationId:row.conversation_id,replyToId:row.reply_to_id!=null?Number(row.reply_to_id):null,senderType:row.sender_type,senderId:row.sender_id,body:row.body,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapTaskActor(row){return{taskId:row.task_id,actorType:row.actor_type,actorId:row.actor_id,role:row.role,permissions:row.permissions??{},createdAt:String(row.created_at)}}function mapDependency(row){return{taskId:row.task_id,dependsOnId:row.depends_on_id,depType:row.dep_type,createdAt:String(row.created_at)}}function mapTag(row){return{id:row.id,name:row.name,color:row.color??"#9ca3af",typeId:row.type_id??null,createdAt:String(row.created_at)}}function mapTaskType(row){return{id:row.id,name:row.name,description:row.description??null,icon:row.icon??null,stages:row.stages,isBuiltin:row.is_builtin,createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapNotificationPref(row){return{actorType:row.actor_type,actorId:row.actor_id,channel:row.channel,priorityThreshold:row.priority_threshold,isDefault:row.is_default,enabled:row.enabled,metadata:row.metadata??{},createdAt:String(row.created_at),updatedAt:String(row.updated_at)}}function mapStageLog(row){return{id:Number(row.id),taskId:row.task_id,fromStage:row.from_stage??null,toStage:row.to_stage,actorType:row.actor_type??null,actorId:row.actor_id??null,runId:row.run_id??null,gateType:row.gate_type??null,createdAt:String(row.created_at)}}function mapConversationMember(row){return{conversationId:row.conversation_id,actorType:row.actor_type,actorId:row.actor_id,role:row.role,joinedAt:String(row.joined_at)}}function mapProject(row){return{id:row.id,name:row.name,repoPath:str2(row.repo_path),description:str2(row.description),leaderAgent:str2(row.leader_agent),tmuxSession:str2(row.tmux_session),status:strOrDefault(row.status,"active"),archivedAt:str2(row.archived_at),createdAt:String(row.created_at)}}function getRepoPath(){try{return execSync7("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}async function resolveTaskId(idOrSeq,repoPath){let sql=await getConnection(),repo=repoPath??getRepoPath(),projectSeqMatch=idOrSeq.match(/^([^#]+)#(\d+)$/);if(projectSeqMatch&&!idOrSeq.startsWith("#")){let[,projectName,seqStr]=projectSeqMatch,seq2=Number.parseInt(seqStr,10);if(Number.isNaN(seq2))return null;let rows2=await sql`
|
|
771
771
|
SELECT t.id FROM tasks t
|
|
772
772
|
JOIN projects p ON t.project_id = p.id
|
|
773
773
|
WHERE p.name = ${projectName} AND t.seq = ${seq2}
|
|
@@ -3204,7 +3204,7 @@ ${indented}`}function formatHumanOutput(events,label){let lines=[];if(lines.push
|
|
|
3204
3204
|
WHERE c.content ILIKE ${`%${query2}%`}
|
|
3205
3205
|
ORDER BY c.timestamp DESC
|
|
3206
3206
|
LIMIT ${limit}
|
|
3207
|
-
`;if(options.json){console.log(JSON.stringify(rows,null,2));return}if(rows.length===0){console.log(`No results for "${query2}".`);return}console.log(""),console.log(`Search: "${query2}" (${rows.length} results)`),console.log("\u2500".repeat(60));for(let r of rows){let preview=String(r.content).replace(/\n/g," ").slice(0,100),agent=r.agent_id??"(unknown)",time=r.timestamp?new Date(r.timestamp).toLocaleTimeString():"??:??";console.log(` [${time}] ${agent} (${r.role}): ${preview}`)}console.log("")}init_agent_directory();init_genie_config2();import{resolve as resolvePath2}from"path";init_audit();init_genie_config2();async function resolveOmniApiUrl(){let envUrl=process.env.OMNI_API_URL;if(envUrl)return envUrl;return(await loadGenieConfig()).omni?.apiUrl??null}async function resolveOmniApiKey(){let envKey=process.env.OMNI_API_KEY;if(envKey)return envKey;return(await loadGenieConfig()).omni?.apiKey}async function registerAgentInOmni(agentName,options){let apiUrl=await resolveOmniApiUrl();if(!apiUrl)return null;let apiKey=await resolveOmniApiKey(),body={name:agentName,provider:"claude",model:options?.model,agentType:"assistant",capabilities:options?.roles??[],metadata:{source:"genie",sessionIsolation:{perPerson:!0,perChannel:!0},registeredAt:new Date().toISOString()}},traceId=generateTraceId();try{let headers={"Content-Type":"application/json","X-Trace-Id":traceId};if(apiKey)headers.Authorization=`Bearer ${apiKey}`;let response=await fetch(`${apiUrl}/api/v2/agents`,{method:"POST",headers,body:JSON.stringify(body),signal:AbortSignal.timeout(1e4)});if(!response.ok){let text=await response.text().catch(()=>"");return console.warn(`Warning: Omni registration failed (HTTP ${response.status}): ${text}`),recordAuditEvent("omni",agentName,"registration_error",getActor(),{traceId,status:response.status,error:text.slice(0,200)}).catch(()=>{}),null}let result2=await response.json();return recordAuditEvent("omni",agentName,"registration_success",getActor(),{traceId,omniAgentId:result2.data.id}).catch(()=>{}),result2.data.id}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);return console.warn(`Warning: Omni registration failed: ${message}`),recordAuditEvent("omni",agentName,"registration_error",getActor(),{traceId,error:message.slice(0,200)}).catch(()=>{}),null}}async function findOmniAgent(agentName){let apiUrl=await resolveOmniApiUrl();if(!apiUrl)return null;let apiKey=await resolveOmniApiKey(),traceId=generateTraceId();try{let headers={"X-Trace-Id":traceId};if(apiKey)headers.Authorization=`Bearer ${apiKey}`;let response=await fetch(`${apiUrl}/api/v2/agents?name=${encodeURIComponent(agentName)}`,{method:"GET",headers,signal:AbortSignal.timeout(1e4)});if(!response.ok)return null;return(await response.json()).data?.find((a)=>a.name===agentName&&a.isActive)?.id??null}catch{return null}}init_agent_directory();init_agent_sync();init_audit();init_builtin_agents();init_defaults();init_frontmatter();init_genie_config2();init_workspace();import{resolve as resolvePath}from"path";function registerDirNamespace(program2){let dir=program2.command("dir").description("Agent directory management"),addCmd=dir.command("add <name>").description("Register an agent in the directory").requiredOption("--dir <path>","Agent folder (CWD + AGENTS.md)").option("--repo <path>","Default git repo (overridden by team)").option("--prompt-mode <mode>","Prompt mode: append or system","append").option("--model <model>","Default model (sonnet, opus, codex)").option("--roles <roles...>","Built-in roles this agent can orchestrate").option("--permission-preset <preset>","Permission preset: full, read-only, chat-only").option("--allow <tools>",'Comma-separated tool allow list (e.g. "Read,Glob,Grep,Bash")').option("--bash-allow <patterns>","Comma-separated regex patterns for allowed bash commands").option("--global","Write to global directory instead of project");registerSdkFlags(addCmd),addCmd.action(async(name,options)=>{try{await handleDirAdd(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("rm <name>").description("Remove an agent from the directory").option("--global","Remove from global directory instead of project").action(async(name,options)=>{try{let removed=await rm3(name,{global:options.global});if(recordAuditEvent("item",name,"item_removed",getActor(),{type:"agent",source:"dir_rm"}).catch(()=>{}),removed){let scope=options.global?"global":"project";console.log(`Agent "${name}" removed from ${scope} directory.`)}else console.error(`Agent "${name}" not found in directory.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("ls [name]").description("List all agents or show single entry details").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)await showEntry2(name,options.json);else await listEntries2(options.json,options.builtins,options.all)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});let editCmd=dir.command("edit <name>").description("Update an agent directory entry").option("--dir <path>","Agent folder (CWD + AGENTS.md)").option("--repo <path>","Default git repo").option("--prompt-mode <mode>","Prompt mode: append or system").option("--model <model>","Default model").option("--provider <provider>","AI provider: claude or codex").option("--color <color>","Display color for TUI").option("--description <desc>","Agent description").option("--roles <roles...>","Built-in roles this agent can orchestrate").option("--permission-preset <preset>","Permission preset: full, read-only, chat-only").option("--allow <tools>",'Comma-separated tool allow list (e.g. "Read,Glob,Grep,Bash")').option("--bash-allow <patterns>","Comma-separated regex patterns for allowed bash commands").option("--global","Edit in global directory instead of project");registerSdkFlags(editCmd),editCmd.action(async(name,options)=>{try{await handleEdit(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("sync").description("Sync agents from workspace agents/ directory").action(async()=>{try{await handleDirSync()}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("export <name>").description("Print full AGENTS.md frontmatter for an agent from PG state").option("--stdout","Print to stdout as raw YAML (default)").option("--json","Print resolved fields as nested JSON with declared/resolved/source").action(async(name,options)=>{try{await handleDirExport(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}async function handleDirAdd(name,options){let promptMode=validatePromptMode(options.promptMode),resolvedDir=resolvePath(options.dir);if(options.repo)validateRepoPath(options.repo);let permissions=buildPermissions(options.permissionPreset,options.allow,options.bashAllow),sdk=buildSdkConfig(options),entry=await add({name,dir:resolvedDir,repo:options.repo?resolvePath(options.repo):void 0,promptMode,model:options.model,roles:normalizeRoles(options.roles),...permissions&&{permissions},...sdk&&{sdk}},{global:options.global});recordAuditEvent("item",name,"item_registered",getActor(),{type:"agent",source:"dir_add"}).catch(()=>{});let scope=options.global?"global":"project";console.log(`Agent "${entry.name}" registered (${scope}).`),printEntry(entry)}async function handleEdit(name,options){let updates={};if(options.dir)updates.dir=resolvePath(options.dir);if(options.repo)updates.repo=resolvePath(options.repo);if(options.promptMode)updates.promptMode=validatePromptMode(options.promptMode);if(options.model)updates.model=options.model;if(options.provider)updates.provider=options.provider;if(options.color)updates.color=options.color;if(options.description)updates.description=options.description;if(options.roles)updates.roles=normalizeRoles(options.roles);let permissions=buildPermissions(options.permissionPreset,options.allow,options.bashAllow);if(permissions)updates.permissions=permissions;let sdk=buildSdkConfig(options);if(sdk)updates.sdk=sdk;if(Object.keys(updates).length===0)console.error("No fields to update. Provide at least one of: --dir, --repo, --prompt-mode, --model, --provider, --color, --description, --roles, --permission-preset, --allow, --bash-allow, --sdk-*"),process.exit(1);let entry=await edit(name,updates,{global:options.global});syncFrontmatterToDisk(entry,updates),recordAuditEvent("item",name,"item_updated",getActor(),{type:"agent",source:"dir_edit"}).catch(()=>{});let scope=options.global?"global":"project";console.log(`Agent "${name}" updated (${scope}).`),printEntry(entry)}async function handleDirSync(){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)}async function handleDirExport(name,options){let entry=await get2(name);if(!entry)console.error(`Agent "${name}" not found in directory.`),process.exit(1);if(options.json){let ctx=buildDirResolveContext(name),output={name:entry.name};for(let field of RESOLVED_FIELDS){let declared=entry[field]??null,result2=resolveFieldWithSource(entry,field,ctx);output[field]={declared:declared??null,resolved:result2.value,source:result2.source}}console.log(JSON.stringify(output,null,2));return}let fm={};if(entry.name)fm.name=entry.name;if(entry.description)fm.description=entry.description;if(entry.model)fm.model=entry.model;if(entry.color)fm.color=entry.color;if(entry.promptMode)fm.promptMode=entry.promptMode;if(entry.provider)fm.provider=entry.provider;if(entry.sdk&&Object.keys(entry.sdk).length>0){let{serializeSdkConfig:serializeSdkConfig2}=await Promise.resolve().then(() => (init_frontmatter_writer(),exports_frontmatter_writer));fm.sdk=serializeSdkConfig2(entry.sdk)}let yamlStr=(await Promise.resolve().then(() => (init_js_yaml(),exports_js_yaml))).dump(fm,{lineWidth:-1,noRefs:!0,sortKeys:!1,quotingType:'"'});console.log(`---
|
|
3207
|
+
`;if(options.json){console.log(JSON.stringify(rows,null,2));return}if(rows.length===0){console.log(`No results for "${query2}".`);return}console.log(""),console.log(`Search: "${query2}" (${rows.length} results)`),console.log("\u2500".repeat(60));for(let r of rows){let preview=String(r.content).replace(/\n/g," ").slice(0,100),agent=r.agent_id??"(unknown)",time=r.timestamp?new Date(r.timestamp).toLocaleTimeString():"??:??";console.log(` [${time}] ${agent} (${r.role}): ${preview}`)}console.log("")}init_agent_directory();init_genie_config2();import{resolve as resolvePath2}from"path";init_audit();init_genie_config2();async function resolveOmniApiUrl(){let envUrl=process.env.OMNI_API_URL;if(envUrl)return envUrl;return(await loadGenieConfig()).omni?.apiUrl??null}async function resolveOmniApiKey(){let envKey=process.env.OMNI_API_KEY;if(envKey)return envKey;return(await loadGenieConfig()).omni?.apiKey}async function registerAgentInOmni(agentName,options){let apiUrl=await resolveOmniApiUrl();if(!apiUrl)return null;let apiKey=await resolveOmniApiKey(),body={name:agentName,provider:"claude",model:options?.model,agentType:"assistant",capabilities:options?.roles??[],metadata:{source:"genie",sessionIsolation:{perPerson:!0,perChannel:!0},registeredAt:new Date().toISOString()}},traceId=generateTraceId();try{let headers={"Content-Type":"application/json","X-Trace-Id":traceId};if(apiKey)headers.Authorization=`Bearer ${apiKey}`;let response=await fetch(`${apiUrl}/api/v2/agents`,{method:"POST",headers,body:JSON.stringify(body),signal:AbortSignal.timeout(1e4)});if(!response.ok){let text=await response.text().catch(()=>"");return console.warn(`Warning: Omni registration failed (HTTP ${response.status}): ${text}`),recordAuditEvent("omni",agentName,"registration_error",getActor(),{traceId,status:response.status,error:text.slice(0,200)}).catch(()=>{}),null}let result2=await response.json();return recordAuditEvent("omni",agentName,"registration_success",getActor(),{traceId,omniAgentId:result2.data.id}).catch(()=>{}),result2.data.id}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);return console.warn(`Warning: Omni registration failed: ${message}`),recordAuditEvent("omni",agentName,"registration_error",getActor(),{traceId,error:message.slice(0,200)}).catch(()=>{}),null}}async function findOmniAgent(agentName){let apiUrl=await resolveOmniApiUrl();if(!apiUrl)return null;let apiKey=await resolveOmniApiKey(),traceId=generateTraceId();try{let headers={"X-Trace-Id":traceId};if(apiKey)headers.Authorization=`Bearer ${apiKey}`;let response=await fetch(`${apiUrl}/api/v2/agents?name=${encodeURIComponent(agentName)}`,{method:"GET",headers,signal:AbortSignal.timeout(1e4)});if(!response.ok)return null;return(await response.json()).data?.find((a)=>a.name===agentName&&a.isActive)?.id??null}catch{return null}}init_agent_directory();init_agent_sync();init_audit();init_builtin_agents();init_defaults();init_frontmatter();init_genie_config2();init_workspace();import{resolve as resolvePath}from"path";function registerDirNamespace(program2){let dir=program2.command("dir").description("Agent directory management"),addCmd=dir.command("add <name>").description("Register an agent in the directory").requiredOption("--dir <path>","Agent folder (CWD + AGENTS.md)").option("--repo <path>","Default git repo (overridden by team)").option("--prompt-mode <mode>","Prompt mode: append or system","append").option("--model <model>","Default model (sonnet, opus, codex)").option("--roles <roles...>","Built-in roles this agent can orchestrate").option("--permission-preset <preset>","Permission preset: full, read-only, chat-only").option("--allow <tools>",'Comma-separated tool allow list (e.g. "Read,Glob,Grep,Bash")').option("--bash-allow <patterns>","Comma-separated regex patterns for allowed bash commands").option("--global","Write to global directory instead of project");registerSdkFlags(addCmd),addCmd.action(async(name,options)=>{try{await handleDirAdd(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("rm <name>").description("Remove an agent from the directory").option("--global","Remove from global directory instead of project").option("--force","Also remove runtime/spawn rows sharing this role (id shapes: <team>-<role>, UUID)").action(async(name,options)=>{try{let result2=await rm3(name,{global:options.global,force:options.force});if(result2.removed){let scope=options.global?"global":"project";console.log(`Agent "${name}" removed from ${scope} directory.`),recordAuditEvent("item",name,"item_removed",getActor(),{type:"agent",source:"dir_rm"}).catch(()=>{})}else if(result2.message)console.error(result2.message),process.exit(1);else console.error(`Agent "${name}" not found in directory.`),process.exit(1)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("ls [name]").description("List all agents or show single entry details").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)await showEntry2(name,options.json);else await listEntries2(options.json,options.builtins,options.all)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}});let editCmd=dir.command("edit <name>").description("Update an agent directory entry").option("--dir <path>","Agent folder (CWD + AGENTS.md)").option("--repo <path>","Default git repo").option("--prompt-mode <mode>","Prompt mode: append or system").option("--model <model>","Default model").option("--provider <provider>","AI provider: claude or codex").option("--color <color>","Display color for TUI").option("--description <desc>","Agent description").option("--roles <roles...>","Built-in roles this agent can orchestrate").option("--permission-preset <preset>","Permission preset: full, read-only, chat-only").option("--allow <tools>",'Comma-separated tool allow list (e.g. "Read,Glob,Grep,Bash")').option("--bash-allow <patterns>","Comma-separated regex patterns for allowed bash commands").option("--global","Edit in global directory instead of project");registerSdkFlags(editCmd),editCmd.action(async(name,options)=>{try{await handleEdit(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("sync").description("Sync agents from workspace agents/ directory").action(async()=>{try{await handleDirSync()}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}}),dir.command("export <name>").description("Print full AGENTS.md frontmatter for an agent from PG state").option("--stdout","Print to stdout as raw YAML (default)").option("--json","Print resolved fields as nested JSON with declared/resolved/source").action(async(name,options)=>{try{await handleDirExport(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}async function handleDirAdd(name,options){let promptMode=validatePromptMode(options.promptMode),resolvedDir=resolvePath(options.dir);if(options.repo)validateRepoPath(options.repo);let permissions=buildPermissions(options.permissionPreset,options.allow,options.bashAllow),sdk=buildSdkConfig(options),entry=await add({name,dir:resolvedDir,repo:options.repo?resolvePath(options.repo):void 0,promptMode,model:options.model,roles:normalizeRoles(options.roles),...permissions&&{permissions},...sdk&&{sdk}},{global:options.global});recordAuditEvent("item",name,"item_registered",getActor(),{type:"agent",source:"dir_add"}).catch(()=>{});let scope=options.global?"global":"project";console.log(`Agent "${entry.name}" registered (${scope}).`),printEntry(entry)}async function handleEdit(name,options){let updates={};if(options.dir)updates.dir=resolvePath(options.dir);if(options.repo)updates.repo=resolvePath(options.repo);if(options.promptMode)updates.promptMode=validatePromptMode(options.promptMode);if(options.model)updates.model=options.model;if(options.provider)updates.provider=options.provider;if(options.color)updates.color=options.color;if(options.description)updates.description=options.description;if(options.roles)updates.roles=normalizeRoles(options.roles);let permissions=buildPermissions(options.permissionPreset,options.allow,options.bashAllow);if(permissions)updates.permissions=permissions;let sdk=buildSdkConfig(options);if(sdk)updates.sdk=sdk;if(Object.keys(updates).length===0)console.error("No fields to update. Provide at least one of: --dir, --repo, --prompt-mode, --model, --provider, --color, --description, --roles, --permission-preset, --allow, --bash-allow, --sdk-*"),process.exit(1);let entry=await edit(name,updates,{global:options.global});syncFrontmatterToDisk(entry,updates),recordAuditEvent("item",name,"item_updated",getActor(),{type:"agent",source:"dir_edit"}).catch(()=>{});let scope=options.global?"global":"project";console.log(`Agent "${name}" updated (${scope}).`),printEntry(entry)}async function handleDirSync(){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)}async function handleDirExport(name,options){let entry=await get2(name);if(!entry)console.error(`Agent "${name}" not found in directory.`),process.exit(1);if(options.json){let ctx=buildDirResolveContext(name),output={name:entry.name};for(let field of RESOLVED_FIELDS){let declared=entry[field]??null,result2=resolveFieldWithSource(entry,field,ctx);output[field]={declared:declared??null,resolved:result2.value,source:result2.source}}console.log(JSON.stringify(output,null,2));return}let fm={};if(entry.name)fm.name=entry.name;if(entry.description)fm.description=entry.description;if(entry.model)fm.model=entry.model;if(entry.color)fm.color=entry.color;if(entry.promptMode)fm.promptMode=entry.promptMode;if(entry.provider)fm.provider=entry.provider;if(entry.sdk&&Object.keys(entry.sdk).length>0){let{serializeSdkConfig:serializeSdkConfig2}=await Promise.resolve().then(() => (init_frontmatter_writer(),exports_frontmatter_writer));fm.sdk=serializeSdkConfig2(entry.sdk)}let yamlStr=(await Promise.resolve().then(() => (init_js_yaml(),exports_js_yaml))).dump(fm,{lineWidth:-1,noRefs:!0,sortKeys:!1,quotingType:'"'});console.log(`---
|
|
3208
3208
|
${yamlStr}---`)}function buildDirResolveContext(agentName){let ctx={};try{let ws=findWorkspace();if(ws){let wsConfig=getWorkspaceConfig(ws.root);if(ctx.workspaceDefaults=wsConfig.agents?.defaults,agentName.includes("/")){let parentName=agentName.split("/")[0],{existsSync:existsSync27,readFileSync:readFileSync17}=__require("fs"),{join:join33}=__require("path"),parentAgentsMd=join33(ws.root,"agents",parentName,"AGENTS.md");if(existsSync27(parentAgentsMd)){let parentFm=parseFrontmatter(readFileSync17(parentAgentsMd,"utf-8"));ctx.parent={name:parentName,fields:parentFm}}}}}catch{}return ctx}function validateRepoPath(repo){if(repo.startsWith("/")||repo.startsWith("~/")||repo.startsWith("./")||repo.startsWith("../"))return;throw Error(`Invalid --repo value "${repo}". Must be a path (absolute "/...", home-relative "~/...", or dot-relative "./..." / "../..."). Got a bare word instead.`)}function validatePromptMode(mode){if(mode!=="system"&&mode!=="append")throw Error(`Invalid prompt mode "${mode}". Must be "append" or "system".`);return mode}function printEntry(entry){if(console.log(` Name: ${entry.name}`),console.log(` Dir: ${contractPath(entry.dir)}`),entry.repo)console.log(` Repo: ${contractPath(entry.repo)}`);if(console.log(` PromptMode: ${entry.promptMode}`),entry.model)console.log(` Model: ${entry.model}`);if(entry.provider)console.log(` Provider: ${entry.provider}`);if(entry.color)console.log(` Color: ${entry.color}`);if(entry.description)console.log(` Description: ${entry.description}`);if(entry.roles?.length)console.log(` Roles: ${entry.roles.join(", ")}`);if(entry.permissions?.preset)console.log(` Permissions: preset=${entry.permissions.preset}`);else if(entry.permissions?.allow){if(console.log(` Permissions: allow=${entry.permissions.allow.join(",")}`),entry.permissions.bashAllowPatterns?.length)console.log(` Bash Allow: ${entry.permissions.bashAllowPatterns.join(", ")}`)}if(entry.sdk)printSdkConfig(entry.sdk);console.log(` Registered: ${entry.registeredAt}`)}async function showEntry2(name,json2){let resolved=await resolve3(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(`
|
|
3209
3209
|
(built-in ${resolved.entry.registeredAt==="(built-in)"?"agent":"agent"})`);console.log(""),printEntry(resolved.entry),console.log("")}async function listEntries2(json2,includeBuiltins,_includeArchived){let entries=await ls();if(json2){listEntriesJson(entries,includeBuiltins);return}if(entries.length===0&&!includeBuiltins){console.log(`
|
|
3210
3210
|
No agents registered. Add one with: genie dir add <name> --dir <path>`),console.log(`Use --builtins to also see built-in roles and council members.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genie",
|
|
3
|
-
"version": "4.260418.
|
|
3
|
+
"version": "4.260418.7",
|
|
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"
|