@keepur/hive 0.1.6 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,7 +48,7 @@ ${r.soul??"(not set)"}`),i.push(`
48
48
  --- System Prompt ---
49
49
  ${r.systemPrompt??"(not set)"}`);let o=r.updatedAt instanceof Date?r.updatedAt.toISOString():String(r.updatedAt??"");return i.push(`
50
50
  Updated: ${o} by ${r.updatedBy??"unknown"}`),{content:[{type:"text",text:i.join(`
51
- `)}]}});B.registerTool("agent_create",{title:"Create Agent",description:"Create a new agent definition. Required: _id, name, model, homeBase. Archetype is optional \u2014 pass it when the role is a discipline with shared infrastructure (see list_archetypes). Soul/systemPrompt shape the agent's voice and role; if omitted they default to empty strings. Additional tuning (channels, schedule, budget, autonomy, archetypeConfig, etc.) goes in `fields`.",inputSchema:{_id:z.string().describe("Agent ID (lowercase with hyphens, e.g. 'my-agent')"),name:z.string().describe("Display name for the agent"),model:z.string().describe("Model to use (e.g. 'claude-sonnet-4-6', 'claude-haiku-4-5')"),homeBase:z.string().describe("Primary Slack channel for scheduler delivery and default identity (e.g. 'agent-<id>'). The channel must exist in Slack."),soul:z.string().optional().describe("Personality / voice / character definition (5-15 lines). Shapes how the agent talks."),systemPrompt:z.string().optional().describe("Role definition and guardrails. Concise. Instance-specific flavor \u2014 archetype framing layers underneath."),archetype:z.string().optional().describe("Discipline id from list_archetypes (e.g. 'software-engineer'). Omit for plain unstructured agents."),title:z.string().optional().describe("Customer-facing title (e.g. 'VP Engineering'). Typically paired with archetype."),fields:z.record(z.string(),z.any()).optional().describe("Additional fields (channels, passiveChannels, schedule, coreServers override, delegateServers, plugins, autonomy, archetypeConfig, budgetUsd, maxTurns, etc.)")}},async({_id:e,name:r,model:i,homeBase:o,soul:t,systemPrompt:n,archetype:a,title:c,fields:u})=>{if(await N.findOne({_id:e}))return{content:[{type:"text",text:`Agent '${e}' already exists. Use agent_update to modify it.`}],isError:!0};if(!o||o.trim()==="")return{content:[{type:"text",text:`Missing required field: homeBase (primary channel for scheduled delivery, e.g. 'agent-${e}').`}],isError:!0};if(a!==void 0&&!zn(a)){let _=Sn().join(", ")||"(none registered)";return{content:[{type:"text",text:`Unknown archetype: "${a}". Known: ${_}.`}],isError:!0}}let l=u??{},p=new Date,$={_id:e,name:r,model:i,icon:l.icon??T.icon,channels:l.channels??[],homeBase:o.trim(),passiveChannels:l.passiveChannels??[...T.passiveChannels],keywords:l.keywords??[...T.keywords],isDefault:l.isDefault??!1,coreServers:l.coreServers??[...T.coreServers],delegateServers:l.delegateServers??[...T.delegateServers],delegatePrompts:l.delegatePrompts??{...T.delegatePrompts},plugins:l.plugins,metadata:l.metadata,soul:t??l.soul??"",systemPrompt:n??l.systemPrompt??"",archetype:a,title:c,archetypeConfig:l.archetypeConfig,schedule:l.schedule??[...T.schedule],subscribe:l.subscribe,budgetUsd:l.budgetUsd??T.budgetUsd,maxTurns:l.maxTurns??T.maxTurns,maxConcurrent:l.maxConcurrent??T.maxConcurrent,timeoutMs:l.timeoutMs??T.timeoutMs,disabled:l.disabled??!1,slackBot:l.slackBot,autonomy:l.autonomy,resourceTiers:l.resourceTiers,betas:l.betas,catches:l.catches,createdAt:p,updatedAt:p,updatedBy:Tt};return await N.insertOne($),{content:[{type:"text",text:`Agent '${e}' (${r}) created with model ${i}${a?` \u2014 archetype ${a}`:""}. Change will take effect within 30 seconds.`}]}});B.registerTool("agent_update",{title:"Update Agent",description:"Update fields on an existing agent definition. Saves a version snapshot before mutation. Cannot change _id. Creation-boundary fields (homeBase, archetype, title, soul, systemPrompt) are promoted to top-level for discoverability; everything else goes in `fields`.",inputSchema:{agent_id:z.string().describe("The agent ID to update"),homeBase:z.string().optional().describe("Primary Slack channel for scheduler delivery."),soul:z.string().optional().describe("Personality / voice / character definition."),systemPrompt:z.string().optional().describe("Role definition and guardrails."),archetype:z.string().optional().describe("Discipline id from list_archetypes. Pass null-style empty string to clear (note: fields.archetype: null also works via the fields bag)."),title:z.string().optional().describe("Customer-facing title."),fields:z.record(z.string(),z.any()).optional().describe("Additional fields (channels, schedule, autonomy, archetypeConfig, budgetUsd, model, etc.)")}},async({agent_id:e,homeBase:r,soul:i,systemPrompt:o,archetype:t,title:n,fields:a})=>{if(!await N.findOne({_id:e}))return{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0};let u={...a??{}};if(r!==void 0&&(u.homeBase=r),i!==void 0&&(u.soul=i),o!==void 0&&(u.systemPrompt=o),t!==void 0&&(u.archetype=t),n!==void 0&&(u.title=n),"_id"in u)return{content:[{type:"text",text:"Cannot change _id. Create a new agent instead."}],isError:!0};if(delete u.createdAt,typeof u.archetype=="string"&&u.archetype.length>0&&!zn(u.archetype)){let l=Sn().join(", ")||"(none registered)";return{content:[{type:"text",text:`Unknown archetype: "${u.archetype}". Known: ${l}.`}],isError:!0}}let s=Object.keys(u);return s.length===0?{content:[{type:"text",text:`No fields to update for '${e}'.`}],isError:!0}:(await Nt(e,s),await N.updateOne({_id:e},{$set:{...u,updatedAt:new Date,updatedBy:Tt}}),{content:[{type:"text",text:`Agent '${e}' updated: ${s.join(", ")}. Version saved. Change will take effect within 30 seconds.`}]})});B.registerTool("agent_delete",{title:"Delete Agent",description:"Delete an agent definition. Saves a version snapshot before deletion. Requires confirm=true.",inputSchema:{agent_id:z.string().describe("The agent ID to delete"),confirm:z.boolean().describe("Must be true to confirm deletion")}},async({agent_id:e,confirm:r})=>r?await N.findOne({_id:e})?(await Nt(e,["DELETED"]),await N.deleteOne({_id:e}),{content:[{type:"text",text:`Agent '${e}' deleted. Version snapshot saved. Change will take effect within 30 seconds.`}]}):{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0}:{content:[{type:"text",text:"Deletion not confirmed. Set confirm=true to proceed."}],isError:!0});B.registerTool("agent_enable",{title:"Enable Agent",description:"Bring a disabled agent back online (sets disabled=false).",inputSchema:{agent_id:z.string().describe("The agent ID to enable")}},async({agent_id:e})=>await N.findOne({_id:e})?(await Nt(e,["disabled"]),await N.updateOne({_id:e},{$set:{disabled:!1,updatedAt:new Date,updatedBy:Tt}}),{content:[{type:"text",text:`Agent '${e}' enabled. Version saved. Change will take effect within 30 seconds.`}]}):{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0});B.registerTool("agent_disable",{title:"Disable Agent",description:"Take an agent offline (sets disabled=true). The agent stops receiving messages and active sessions are aborted.",inputSchema:{agent_id:z.string().describe("The agent ID to disable")}},async({agent_id:e})=>await N.findOne({_id:e})?(await Nt(e,["disabled"]),await N.updateOne({_id:e},{$set:{disabled:!0,updatedAt:new Date,updatedBy:Tt}}),{content:[{type:"text",text:`Agent '${e}' disabled. Version saved. Change will take effect within 30 seconds.`}]}):{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0});B.registerTool("agent_history",{title:"Agent Version History",description:"List version history for an agent definition, sorted newest first.",inputSchema:{agent_id:z.string().describe("The agent ID"),limit:z.number().optional().describe("Max entries to return (default 10)")}},async({agent_id:e,limit:r})=>{let i=r??10,o=await wn.find({agentId:e}).sort({createdAt:-1}).limit(i).toArray();if(o.length===0)return{content:[{type:"text",text:`No version history for '${e}'.`}]};let t=o.map((n,a)=>{let c=n.createdAt instanceof Date?n.createdAt.toISOString():String(n.createdAt),u=n.changedFields.join(", "),s=n.snapshot?.updatedBy?` (by ${n.snapshot.updatedBy})`:"";return`[${a}] ${c} \u2014 changed: ${u}${s}`});return{content:[{type:"text",text:`Version history for '${e}' (${o.length} entries):
51
+ `)}]}});B.registerTool("agent_create",{title:"Create Agent",description:"Create a new agent definition. Required: _id, name, model, homeBase. Archetype is optional \u2014 pass it when the role is a discipline with shared infrastructure (see list_archetypes). Soul/systemPrompt shape the agent's voice and role; if omitted they default to empty strings. Additional tuning (channels, schedule, budget, autonomy, archetypeConfig, etc.) goes in `fields`.",inputSchema:{_id:z.string().describe("Agent ID (lowercase with hyphens, e.g. 'my-agent')"),name:z.string().describe("Display name for the agent"),model:z.string().describe("Model to use (e.g. 'claude-sonnet-4-6', 'claude-haiku-4-5')"),homeBase:z.string().describe("Primary Slack channel for scheduler delivery and default identity (e.g. 'agent-<id>'). The channel must exist in Slack."),soul:z.string().optional().describe("Personality / voice / character definition (5-15 lines). Shapes how the agent talks."),systemPrompt:z.string().optional().describe("Role definition and guardrails. Concise. Instance-specific flavor \u2014 archetype framing layers underneath."),archetype:z.string().optional().describe("Discipline id from list_archetypes (e.g. 'software-engineer'). Omit for plain unstructured agents."),title:z.string().optional().describe("Customer-facing title (e.g. 'VP Engineering'). Typically paired with archetype."),fields:z.record(z.string(),z.any()).optional().describe("Additional fields (channels, passiveChannels, schedule, coreServers override, delegateServers, plugins, autonomy, archetypeConfig, budgetUsd, maxTurns, etc.)")}},async({_id:e,name:r,model:i,homeBase:o,soul:t,systemPrompt:n,archetype:a,title:c,fields:u})=>{if(await N.findOne({_id:e}))return{content:[{type:"text",text:`Agent '${e}' already exists. Use agent_update to modify it.`}],isError:!0};if(!o||o.trim()==="")return{content:[{type:"text",text:`Missing required field: homeBase (primary channel for scheduled delivery, e.g. 'agent-${e}').`}],isError:!0};if(a!==void 0&&!zn(a)){let _=Sn().join(", ")||"(none registered)";return{content:[{type:"text",text:`Unknown archetype: "${a}". Known: ${_}.`}],isError:!0}}let l=u??{},p=new Date,$={_id:e,name:r,aliases:l.aliases,model:i,icon:l.icon??T.icon,channels:l.channels??[],homeBase:o.trim(),passiveChannels:l.passiveChannels??[...T.passiveChannels],keywords:l.keywords??[...T.keywords],isDefault:l.isDefault??!1,coreServers:l.coreServers??[...T.coreServers],delegateServers:l.delegateServers??[...T.delegateServers],delegatePrompts:l.delegatePrompts??{...T.delegatePrompts},plugins:l.plugins,metadata:l.metadata,soul:t??l.soul??"",systemPrompt:n??l.systemPrompt??"",archetype:a,title:c,archetypeConfig:l.archetypeConfig,schedule:l.schedule??[...T.schedule],subscribe:l.subscribe,budgetUsd:l.budgetUsd??T.budgetUsd,maxTurns:l.maxTurns??T.maxTurns,maxConcurrent:l.maxConcurrent??T.maxConcurrent,timeoutMs:l.timeoutMs??T.timeoutMs,disabled:l.disabled??!1,slackBot:l.slackBot,autonomy:l.autonomy,resourceTiers:l.resourceTiers,betas:l.betas,catches:l.catches,createdAt:p,updatedAt:p,updatedBy:Tt};return await N.insertOne($),{content:[{type:"text",text:`Agent '${e}' (${r}) created with model ${i}${a?` \u2014 archetype ${a}`:""}. Change will take effect within 30 seconds.`}]}});B.registerTool("agent_update",{title:"Update Agent",description:"Update fields on an existing agent definition. Saves a version snapshot before mutation. Cannot change _id. Creation-boundary fields (homeBase, archetype, title, soul, systemPrompt) are promoted to top-level for discoverability; everything else goes in `fields`.",inputSchema:{agent_id:z.string().describe("The agent ID to update"),homeBase:z.string().optional().describe("Primary Slack channel for scheduler delivery."),soul:z.string().optional().describe("Personality / voice / character definition."),systemPrompt:z.string().optional().describe("Role definition and guardrails."),archetype:z.string().optional().describe("Discipline id from list_archetypes. Pass null-style empty string to clear (note: fields.archetype: null also works via the fields bag)."),title:z.string().optional().describe("Customer-facing title."),fields:z.record(z.string(),z.any()).optional().describe("Additional fields (channels, schedule, autonomy, archetypeConfig, budgetUsd, model, etc.)")}},async({agent_id:e,homeBase:r,soul:i,systemPrompt:o,archetype:t,title:n,fields:a})=>{if(!await N.findOne({_id:e}))return{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0};let u={...a??{}};if(r!==void 0&&(u.homeBase=r),i!==void 0&&(u.soul=i),o!==void 0&&(u.systemPrompt=o),t!==void 0&&(u.archetype=t),n!==void 0&&(u.title=n),"_id"in u)return{content:[{type:"text",text:"Cannot change _id. Create a new agent instead."}],isError:!0};if(delete u.createdAt,typeof u.archetype=="string"&&u.archetype.length>0&&!zn(u.archetype)){let l=Sn().join(", ")||"(none registered)";return{content:[{type:"text",text:`Unknown archetype: "${u.archetype}". Known: ${l}.`}],isError:!0}}let s=Object.keys(u);return s.length===0?{content:[{type:"text",text:`No fields to update for '${e}'.`}],isError:!0}:(await Nt(e,s),await N.updateOne({_id:e},{$set:{...u,updatedAt:new Date,updatedBy:Tt}}),{content:[{type:"text",text:`Agent '${e}' updated: ${s.join(", ")}. Version saved. Change will take effect within 30 seconds.`}]})});B.registerTool("agent_delete",{title:"Delete Agent",description:"Delete an agent definition. Saves a version snapshot before deletion. Requires confirm=true.",inputSchema:{agent_id:z.string().describe("The agent ID to delete"),confirm:z.boolean().describe("Must be true to confirm deletion")}},async({agent_id:e,confirm:r})=>r?await N.findOne({_id:e})?(await Nt(e,["DELETED"]),await N.deleteOne({_id:e}),{content:[{type:"text",text:`Agent '${e}' deleted. Version snapshot saved. Change will take effect within 30 seconds.`}]}):{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0}:{content:[{type:"text",text:"Deletion not confirmed. Set confirm=true to proceed."}],isError:!0});B.registerTool("agent_enable",{title:"Enable Agent",description:"Bring a disabled agent back online (sets disabled=false).",inputSchema:{agent_id:z.string().describe("The agent ID to enable")}},async({agent_id:e})=>await N.findOne({_id:e})?(await Nt(e,["disabled"]),await N.updateOne({_id:e},{$set:{disabled:!1,updatedAt:new Date,updatedBy:Tt}}),{content:[{type:"text",text:`Agent '${e}' enabled. Version saved. Change will take effect within 30 seconds.`}]}):{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0});B.registerTool("agent_disable",{title:"Disable Agent",description:"Take an agent offline (sets disabled=true). The agent stops receiving messages and active sessions are aborted.",inputSchema:{agent_id:z.string().describe("The agent ID to disable")}},async({agent_id:e})=>await N.findOne({_id:e})?(await Nt(e,["disabled"]),await N.updateOne({_id:e},{$set:{disabled:!0,updatedAt:new Date,updatedBy:Tt}}),{content:[{type:"text",text:`Agent '${e}' disabled. Version saved. Change will take effect within 30 seconds.`}]}):{content:[{type:"text",text:`Agent '${e}' not found.`}],isError:!0});B.registerTool("agent_history",{title:"Agent Version History",description:"List version history for an agent definition, sorted newest first.",inputSchema:{agent_id:z.string().describe("The agent ID"),limit:z.number().optional().describe("Max entries to return (default 10)")}},async({agent_id:e,limit:r})=>{let i=r??10,o=await wn.find({agentId:e}).sort({createdAt:-1}).limit(i).toArray();if(o.length===0)return{content:[{type:"text",text:`No version history for '${e}'.`}]};let t=o.map((n,a)=>{let c=n.createdAt instanceof Date?n.createdAt.toISOString():String(n.createdAt),u=n.changedFields.join(", "),s=n.snapshot?.updatedBy?` (by ${n.snapshot.updatedBy})`:"";return`[${a}] ${c} \u2014 changed: ${u}${s}`});return{content:[{type:"text",text:`Version history for '${e}' (${o.length} entries):
52
52
  ${t.join(`
53
53
  `)}`}]}});B.registerTool("agent_rollback",{title:"Rollback Agent",description:"Rollback an agent definition to a previous version. Saves current state first, then replaces with the snapshot. Use agent_history to see available versions.",inputSchema:{agent_id:z.string().describe("The agent ID to rollback"),version_index:z.number().describe("Version index from agent_history (0 = most recent version)")}},async({agent_id:e,version_index:r})=>{if(r<0||!Number.isInteger(r))return{content:[{type:"text",text:"version_index must be a non-negative integer."}],isError:!0};let i=await wn.find({agentId:e}).sort({createdAt:-1}).limit(r+1).toArray();if(i.length<=r)return{content:[{type:"text",text:`Version index ${r} not found for '${e}'. Only ${i.length} versions available.`}],isError:!0};let o=i[r];if(!await N.findOne({_id:e}))return{content:[{type:"text",text:`Agent '${e}' not found \u2014 cannot rollback a deleted agent.`}],isError:!0};await Nt(e,["ROLLBACK"]);let{_id:n,...a}=o.snapshot;await N.updateOne({_id:e},{$set:{...a,updatedAt:new Date,updatedBy:Tt}});let c=o.createdAt instanceof Date?o.createdAt.toISOString():String(o.createdAt);return{content:[{type:"text",text:`Agent '${e}' rolled back to version from ${c}. Current state saved first. Change will take effect within 30 seconds.`}]}});var yf={instanceId:"unknown",servers:{configured:[],unconfigured:[]}},Zt=yf;try{if(process.env.INSTANCE_CAPABILITIES){let e=JSON.parse(process.env.INSTANCE_CAPABILITIES);e&&typeof e=="object"&&"servers"in e&&(Zt=e)}}catch(e){console.error("[hive-admin] Failed to parse INSTANCE_CAPABILITIES, using fallback:",e)}B.registerTool("instance_capabilities",{title:"Instance Capabilities",description:"Report what servers, integrations, and channels are configured on this Hive instance. Use this before creating agents to check what capabilities are available.",inputSchema:{}},async()=>{let e=await N.find({},{projection:{channels:1,passiveChannels:1}}).toArray(),r=new Set;for(let o of e){for(let t of o.channels??[])r.add(t);for(let t of o.passiveChannels??[])r.add(t)}return{content:[{type:"text",text:[`Instance: ${Zt.instanceId}`,`Agents: ${e.length}`,"","## Configured Servers",...Zt.servers.configured.map(o=>` \u2713 ${o}`),"","## Unconfigured Servers (missing credentials)",...Zt.servers.unconfigured.length>0?Zt.servers.unconfigured.map(o=>` \u2717 ${o}`):[" (none \u2014 all servers configured)"],"","## Active Channels",...r.size>0?[...r].sort().map(o=>` #${o}`):[" (no channels assigned)"]].join(`
54
54
  `)}]}});B.registerTool("list_archetypes",{title:"List Archetypes",description:"List registered agent archetypes with self-descriptions. Use this to decide whether an agent you are creating is a discipline-bound archetype (e.g. software-engineer) or a plain unstructured agent.",inputSchema:{}},async()=>{let r=Sn().map(i=>{let o=zn(i);return o?{id:o.id,description:o.description??null,whenToUse:o.whenToUse??null,configSchema:o.configSchema??null}:null}).filter(i=>i!==null);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}});B.registerTool("verify_path",{title:"Verify Filesystem Path",description:"Check that an absolute filesystem path exists and is a directory. Used by the agent-builder skill to validate archetype-config paths (e.g. software-engineer `workshop`) before agent creation, so the caller catches typos at creation time instead of at agent-load time.",inputSchema:{path:z.string().describe("Absolute filesystem path to verify. Must start with '/'. Tilde (~) is not expanded \u2014 callers must pre-expand.")}},async({path:e})=>{if(typeof e!="string"||e.length===0)return{content:[{type:"text",text:JSON.stringify({exists:!1,isDirectory:!1,error:"path must be a non-empty string"})}],isError:!0};if(!vf(e))return{content:[{type:"text",text:JSON.stringify({exists:!1,isDirectory:!1,error:`path must be absolute (start with '/'); got "${e}"`})}],isError:!0};let r=hf(e);try{let i=gf(r);return{content:[{type:"text",text:JSON.stringify({exists:!0,isDirectory:i.isDirectory(),resolved:r})}]}}catch{return{content:[{type:"text",text:JSON.stringify({exists:!1,isDirectory:!1,resolved:r})}]}}});process.on("SIGTERM",()=>In.close());process.on("SIGINT",()=>In.close());var xf=new pf;await B.connect(xf);