@automagik/genie 4.260429.16 → 4.260429.18
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
|
@@ -529,7 +529,7 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
|
|
|
529
529
|
`,added}async function fireAgent(teamName,agentName){let config=await getTeam(teamName);if(!config)throw Error(`Team "${teamName}" not found.`);let idx=config.members.indexOf(agentName);if(idx===-1)return!1;config.members.splice(idx,1);let sql=await getConnection();await sql`
|
|
530
530
|
UPDATE teams SET members = ${sql.json(config.members)}
|
|
531
531
|
WHERE name = ${teamName}
|
|
532
|
-
`;try{await killWorkersByName(agentName)}catch{}return!0}async function
|
|
532
|
+
`;try{await killWorkersByName(agentName)}catch{}return!0}async function cleanupTeamGitArtifacts(config){if(config.worktreePath)try{await $2`git -C ${config.repo} worktree remove --force ${config.worktreePath}`.quiet()}catch{try{await $2`rm -rf ${config.worktreePath}`.quiet()}catch{}}try{let branchTip=(await $2`git -C ${config.repo} rev-parse ${config.name}`.quiet()).text().trim(),baseTip="";try{baseTip=(await $2`git -C ${config.repo} rev-parse origin/${config.baseBranch}`.quiet()).text().trim()}catch{try{baseTip=(await $2`git -C ${config.repo} rev-parse ${config.baseBranch}`.quiet()).text().trim()}catch{return}}if(branchTip&&baseTip&&branchTip===baseTip)await $2`git -C ${config.repo} branch -D ${config.name}`.quiet()}catch{}}async function cleanupTeamTmuxSession(tmuxSessionName,teamName){if(!tmuxSessionName)return;try{if(!await findSessionByName(tmuxSessionName))return;let windows=await listWindows(tmuxSessionName),teamWindow=await findWindowByName(tmuxSessionName,teamName);if(tmuxSessionName===teamName||windows.length===1&&windows[0]?.name===teamName)await killSession(tmuxSessionName);else if(teamWindow)await executeTmux2(`kill-window -t '${teamWindow.id}'`)}catch{}}async function archiveTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;let killResults=await Promise.allSettled(config.members.map((member)=>killWorkersByName(member,teamName)));for(let i2=0;i2<killResults.length;i2++)if(killResults[i2].status==="rejected")console.error(` Failed to kill member "${config.members[i2]}": ${killResults[i2].reason}`);await cleanupTeamTmuxSession(config.tmuxSessionName??teamName,teamName),await cleanupTeamGitArtifacts(config);let sql=await getConnection(),archivedAgents=0,updated=!1;if(await sql.begin(async(tx)=>{if((await tx`
|
|
533
533
|
UPDATE teams SET status = 'archived', archived_at = now(), updated_at = now()
|
|
534
534
|
WHERE name = ${teamName}
|
|
535
535
|
`).count===0)return;updated=!0,archivedAgents=(await tx`
|
|
@@ -538,7 +538,7 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
|
|
|
538
538
|
`).count??0}),!updated)return!1;return recordAuditEvent("team",teamName,"archived",getActor(),{repo:config.repo,archivedAgents}).catch(()=>{}),!0}async function unarchiveTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;let restoredStatus="done";if((await(await getConnection())`
|
|
539
539
|
UPDATE teams SET status = ${restoredStatus}, archived_at = NULL, updated_at = now()
|
|
540
540
|
WHERE name = ${teamName}
|
|
541
|
-
`).count===0)return!1;return recordAuditEvent("team",teamName,"unarchived",getActor(),{repo:config.repo,restoredStatus}).catch(()=>{}),!0}async function disbandTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;try{await deleteNativeTeam(teamName)}catch{}for(let member of config.members)try{await killWorkersByName(member,teamName)}catch{}await
|
|
541
|
+
`).count===0)return!1;return recordAuditEvent("team",teamName,"unarchived",getActor(),{repo:config.repo,restoredStatus}).catch(()=>{}),!0}async function disbandTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;try{await deleteNativeTeam(teamName)}catch{}for(let member of config.members)try{await killWorkersByName(member,teamName)}catch{}await cleanupTeamGitArtifacts(config),await cleanupTeamTmuxSession(config.tmuxSessionName??teamName,teamName);let sql=await getConnection(),disbanded=!1;if(await sql.begin(async(tx)=>{if(config.wishSlug)try{let wishFile=`.genie/wishes/${config.wishSlug}/WISH.md`,parent=await tx`
|
|
542
542
|
SELECT id FROM tasks
|
|
543
543
|
WHERE wish_file = ${wishFile} AND repo_path = ${config.repo} AND parent_id IS NULL
|
|
544
544
|
LIMIT 1
|
|
@@ -3912,7 +3912,7 @@ Behavior (idempotent):
|
|
|
3912
3912
|
Exit codes:
|
|
3913
3913
|
0 recovery succeeded (or agent already healed \u2014 second run is a no-op)
|
|
3914
3914
|
1 resume failed; PG surgery state is preserved for retry
|
|
3915
|
-
2 agent not found by id, dir:<name>, custom_name, or role`).action(async(name,options)=>{try{await handleWorkerRecover(name,options)}catch(error2){if(error2 instanceof RecoverAgentNotFoundError)console.error(`Error: ${error2.message}`),process.exit(2);let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_agent_directory();init_genie_config2();import{resolve as resolvePath3}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_migrate();init_agent_sync();init_agent_yaml();init_audit();init_builtin_agents();init_defaults();init_frontmatter();init_genie_config2();init_workspace();import{existsSync as existsSync38,mkdirSync as mkdirSync15,writeFileSync as writeFileSync15}from"fs";import{join as join46,resolve as resolvePath2}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)").option("--explicit-permanent","Override the heal-not-wipe guardrail and delete master agent rows (kind='permanent' with repo_path). Use with care \u2014 these rows own irreplaceable session identity.").action(async(name,options)=>{try{let result2=await rm3(name,{global:options.global,force:options.force,explicitPermanent:options.explicitPermanent});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]").alias("list").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").option("--allow-symlink","Accept a symlinked AGENTS.md at the new --dir (default: rejected \u2014 usually indicates --dir was pointed at the wrong folder)");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=resolvePath2(options.dir);if(options.repo)validateRepoPath(options.repo);let permissions=buildPermissions(options.permissionPreset,options.allow,options.bashAllow),sdk=buildSdkConfig(options),config={promptMode,...options.model!==void 0&&{model:options.model},...options.repo!==void 0&&{repo:resolvePath2(options.repo)},...options.roles!==void 0&&{roles:normalizeRoles(options.roles)},...permissions&&{permissions},...sdk&&{sdk}};mkdirSync15(resolvedDir,{recursive:!0});let agentsMdPath=join46(resolvedDir,"AGENTS.md");if(!existsSync38(agentsMdPath))writeFileSync15(agentsMdPath,scaffoldAgentsMdBody(name));await writeAgentYaml(join46(resolvedDir,"agent.yaml"),config);let
|
|
3915
|
+
2 agent not found by id, dir:<name>, custom_name, or role`).action(async(name,options)=>{try{await handleWorkerRecover(name,options)}catch(error2){if(error2 instanceof RecoverAgentNotFoundError)console.error(`Error: ${error2.message}`),process.exit(2);let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_agent_directory();init_genie_config2();import{resolve as resolvePath3}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_migrate();init_agent_sync();init_agent_yaml();init_audit();init_builtin_agents();init_defaults();init_frontmatter();init_genie_config2();init_workspace();import{existsSync as existsSync38,mkdirSync as mkdirSync15,writeFileSync as writeFileSync15}from"fs";import{join as join46,resolve as resolvePath2}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)").option("--explicit-permanent","Override the heal-not-wipe guardrail and delete master agent rows (kind='permanent' with repo_path). Use with care \u2014 these rows own irreplaceable session identity.").action(async(name,options)=>{try{let result2=await rm3(name,{global:options.global,force:options.force,explicitPermanent:options.explicitPermanent});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]").alias("list").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").option("--allow-symlink","Accept a symlinked AGENTS.md at the new --dir (default: rejected \u2014 usually indicates --dir was pointed at the wrong folder)");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=resolvePath2(options.dir);if(options.repo)validateRepoPath(options.repo);let permissions=buildPermissions(options.permissionPreset,options.allow,options.bashAllow),sdk=buildSdkConfig(options),config={promptMode,...options.model!==void 0&&{model:options.model},...options.repo!==void 0&&{repo:resolvePath2(options.repo)},...options.roles!==void 0&&{roles:normalizeRoles(options.roles)},...permissions&&{permissions},...sdk&&{sdk}};mkdirSync15(resolvedDir,{recursive:!0});let agentsMdPath=join46(resolvedDir,"AGENTS.md");if(!existsSync38(agentsMdPath))writeFileSync15(agentsMdPath,scaffoldAgentsMdBody(name));await writeAgentYaml(join46(resolvedDir,"agent.yaml"),config);let directoryEntry={name,dir:resolvedDir,repo:options.repo?resolvePath2(options.repo):void 0,promptMode,model:options.model,roles:normalizeRoles(options.roles),...permissions&&{permissions},...sdk&&{sdk}},ws=findWorkspace();if((ws?await syncSingleAgentByName(ws.root,name):"not-found")==="not-found"){if(await add(directoryEntry,{global:options.global}),!ws)console.warn("Not in a genie workspace \u2014 directory row created; run `genie dir sync` in a workspace to re-sync.")}recordAuditEvent("item",name,"item_registered",getActor(),{type:"agent",source:"dir_add"}).catch(()=>{});let scope=options.global?"global":"project";console.log(`Agent "${name}" registered (${scope}).`);let entry2=await get2(name);if(entry2)printEntry(entry2)}function scaffoldAgentsMdBody(name){return`# Agent: ${name}
|
|
3916
3916
|
|
|
3917
3917
|
Describe what this agent does, how it behaves, and what it owns.
|
|
3918
3918
|
Runtime config (team, model, permissions, etc.) lives in \`agent.yaml\` \u2014
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automagik/genie",
|
|
3
|
-
"version": "4.260429.
|
|
3
|
+
"version": "4.260429.18",
|
|
4
4
|
"description": "Collaborative terminal toolkit for human + AI workflows. NOTE: the npm distribution is being soft-deprecated — the canonical install is `curl -fsSL https://get.automagik.dev/genie | bash` (cosign + SLSA verified). See https://automagik.dev/genie/security/distribution-sovereignty",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genie",
|
|
3
|
-
"version": "4.260429.
|
|
3
|
+
"version": "4.260429.18",
|
|
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"
|