agentix-cli 0.9.0 → 0.14.0

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.
Files changed (71) hide show
  1. package/README.md +50 -443
  2. package/dist/agent-DW3NYIIL.js +2 -0
  3. package/dist/board-dashboard-6TKE6NMV.js +1435 -0
  4. package/dist/board-dashboard-6TKE6NMV.js.map +1 -0
  5. package/dist/chunk-6U2XOQHU.js +7 -0
  6. package/dist/chunk-6U2XOQHU.js.map +1 -0
  7. package/dist/chunk-DYOBFJLX.js +11 -0
  8. package/dist/chunk-DYOBFJLX.js.map +1 -0
  9. package/dist/chunk-HI24KAEY.js +54 -0
  10. package/dist/chunk-HI24KAEY.js.map +1 -0
  11. package/dist/chunk-ITZEVXZ4.js +2 -0
  12. package/dist/chunk-ITZEVXZ4.js.map +1 -0
  13. package/dist/chunk-M33CB2H4.js +6 -0
  14. package/dist/chunk-M33CB2H4.js.map +1 -0
  15. package/dist/chunk-MCJUAE6V.js +6 -0
  16. package/dist/chunk-MCJUAE6V.js.map +1 -0
  17. package/dist/chunk-NJR5WF5E.js +5 -0
  18. package/dist/chunk-NJR5WF5E.js.map +1 -0
  19. package/dist/chunk-O72LPMBR.js +12 -0
  20. package/dist/chunk-O72LPMBR.js.map +1 -0
  21. package/dist/chunk-QOYAX2FT.js +2 -0
  22. package/dist/chunk-QOYAX2FT.js.map +1 -0
  23. package/dist/chunk-QZP65I2H.js +45 -0
  24. package/dist/chunk-QZP65I2H.js.map +1 -0
  25. package/dist/chunk-RB73FZXJ.js +133 -0
  26. package/dist/chunk-RB73FZXJ.js.map +1 -0
  27. package/dist/chunk-UPT2UMF6.js +159 -0
  28. package/dist/chunk-UPT2UMF6.js.map +1 -0
  29. package/dist/{chunk-SBUX74OU.js → chunk-XVYMZ4M7.js} +5 -5
  30. package/dist/cli.js +53 -50
  31. package/dist/cli.js.map +1 -1
  32. package/dist/compaction-7I3E5QUO.js +28 -0
  33. package/dist/compaction-7I3E5QUO.js.map +1 -0
  34. package/dist/config-7QJ2QJIC.js +2 -0
  35. package/dist/config-mutator-GAEVGHDD.js +2 -0
  36. package/dist/index.d.ts +1715 -106
  37. package/dist/index.js +39 -35
  38. package/dist/index.js.map +1 -1
  39. package/dist/loader-YQE6XJBT.js +2 -0
  40. package/dist/registry-YVAG4EO5.js +2 -0
  41. package/dist/registry-YVAG4EO5.js.map +1 -0
  42. package/dist/{usage-dashboard-2TJQBFSH.js → usage-dashboard-M7AFIGMJ.js} +2 -2
  43. package/dist/workspace-setup-QQTCJY4B.js +2 -0
  44. package/dist/workspace-setup-QQTCJY4B.js.map +1 -0
  45. package/package.json +9 -1
  46. package/dist/agent-QYQVGKLM.js +0 -2
  47. package/dist/chunk-34UAFPK4.js +0 -10
  48. package/dist/chunk-34UAFPK4.js.map +0 -1
  49. package/dist/chunk-BAIQJHQF.js +0 -64
  50. package/dist/chunk-BAIQJHQF.js.map +0 -1
  51. package/dist/chunk-BHDLKX3G.js +0 -6
  52. package/dist/chunk-BHDLKX3G.js.map +0 -1
  53. package/dist/chunk-CJ45Y2IR.js +0 -12
  54. package/dist/chunk-CJ45Y2IR.js.map +0 -1
  55. package/dist/chunk-FRFR27IN.js +0 -3
  56. package/dist/chunk-FRFR27IN.js.map +0 -1
  57. package/dist/chunk-IVVVYXPH.js +0 -136
  58. package/dist/chunk-IVVVYXPH.js.map +0 -1
  59. package/dist/chunk-X32247GM.js +0 -2
  60. package/dist/chunk-X32247GM.js.map +0 -1
  61. package/dist/compaction-E3MQRLTL.js +0 -28
  62. package/dist/compaction-E3MQRLTL.js.map +0 -1
  63. package/dist/config-MSWKC466.js +0 -2
  64. package/dist/loader-6VSM6FSY.js +0 -2
  65. package/dist/registry-FP6FUOXF.js +0 -2
  66. /package/dist/{agent-QYQVGKLM.js.map → agent-DW3NYIIL.js.map} +0 -0
  67. /package/dist/{chunk-SBUX74OU.js.map → chunk-XVYMZ4M7.js.map} +0 -0
  68. /package/dist/{config-MSWKC466.js.map → config-7QJ2QJIC.js.map} +0 -0
  69. /package/dist/{loader-6VSM6FSY.js.map → config-mutator-GAEVGHDD.js.map} +0 -0
  70. /package/dist/{registry-FP6FUOXF.js.map → loader-YQE6XJBT.js.map} +0 -0
  71. /package/dist/{usage-dashboard-2TJQBFSH.js.map → usage-dashboard-M7AFIGMJ.js.map} +0 -0
@@ -1,6 +0,0 @@
1
- import{z as e}from"zod";import{readFileSync as g,existsSync as l}from"fs";import{resolve as d}from"path";function p(n){let r=d(n,".env");if(!l(r))return;let o=g(r,"utf-8");for(let t of o.split(`
2
- `)){let a=t.trim();if(!a||a.startsWith("#"))continue;let i=a.indexOf("=");if(i===-1)continue;let c=a.slice(0,i).trim(),s=a.slice(i+1).trim();process.env[c]||(process.env[c]=s)}}var m=e.object({apiKey:e.string().optional(),defaultModel:e.string().optional(),baseUrl:e.string().optional()}),h=e.object({name:e.string(),workspace:e.string(),tier:e.enum(["claude-code","sdk","orchestrator"]).default("claude-code"),provider:e.string().optional(),model:e.string().optional(),systemPrompt:e.string().optional(),mentions:e.array(e.string()).default([]),maxConcurrent:e.number().default(1),permissionMode:e.string().default("default"),queueMode:e.enum(["collect","followup","drop"]).default("collect"),heartbeat:e.object({enabled:e.boolean().default(!1),intervalMinutes:e.number().default(30),prompt:e.string().default("Check inbox, pending tasks, and system health. Report anything that needs attention."),channel:e.string().default("heartbeat")}).default({})}),b=e.object({token:e.string(),agentBinding:e.string()}),y=e.object({telegram:e.object({enabled:e.boolean().default(!1),accounts:e.record(e.string(),b).default({}),policy:e.object({dm:e.enum(["pair","block"]).default("pair"),group:e.enum(["mention-required","all"]).default("mention-required")}).default({})}).default({}),whatsapp:e.object({enabled:e.boolean().default(!1),sessionDir:e.string().default(".agentx/whatsapp-sessions"),defaultAgent:e.string().optional(),allowFrom:e.array(e.string()).optional(),routes:e.array(e.object({contact:e.string().optional(),group:e.string().optional(),agent:e.string()})).default([])}).default({}),discord:e.object({enabled:e.boolean().default(!1),token:e.string().optional(),agentBinding:e.string().optional()}).default({}),gitlab:e.object({enabled:e.boolean().default(!1),webhookPort:e.number().default(18810),webhookSecret:e.string().optional(),host:e.string().default("https://gitlab.com"),token:e.string().optional(),routes:e.array(e.object({project:e.string(),agent:e.string()})).default([]),agentMappings:e.array(e.object({agentId:e.string(),gitlabUsernames:e.array(e.string()).default([]),keywords:e.array(e.string()).default([]),token:e.string().optional()})).default([])}).default({})}),k=e.object({enabled:e.boolean().default(!0),schedule:e.string(),timezone:e.string().default("UTC"),agent:e.string(),prompt:e.string(),timeout:e.number().default(600),model:e.string().optional(),onError:e.enum(["log","notify","disable"]).default("log"),notify:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional()}),w=e.object({url:e.string(),name:e.string(),token:e.string().optional()}),v=e.object({enabled:e.boolean().default(!1),peers:e.array(w).default([]),discovery:e.enum(["static","mdns"]).default("static"),healthCheck:e.object({interval:e.number().default(60),timeout:e.number().default(10)}).default({})}),j=e.object({node:e.object({id:e.string(),name:e.string(),bind:e.string().default("127.0.0.1:18800")}),providers:e.record(e.string(),m).default({}),agents:e.record(e.string(),h).default({}),channels:y.default({}),crons:e.record(e.string(),k).default({}),mesh:v.default({})});function u(n){if(typeof n=="string")return n.replace(/\$\{(\w+)\}/g,(r,o)=>process.env[o]||"");if(Array.isArray(n))return n.map(u);if(n!==null&&typeof n=="object"){let r={};for(let[o,t]of Object.entries(n))r[o]=u(t);return r}return n}function $(n){let r=n?[n]:[d(process.cwd(),"agentx.json"),d(process.cwd(),".agentx/config.json")];p(process.cwd());let o,t;for(let s of r)if(l(s)){o=g(s,"utf-8"),t=s;break}if(!o||!t)throw new Error(`No config found. Create agentx.json or .agentx/config.json
3
- Searched: ${r.join(", ")}`);let a;try{a=JSON.parse(o)}catch(s){throw new Error(`Invalid JSON in ${t}: ${s.message}`)}let i=u(a),c=j.safeParse(i);if(!c.success){let s=c.error.issues.map(f=>` ${f.path.join(".")}: ${f.message}`).join(`
4
- `);throw new Error(`Config validation failed (${t}):
5
- ${s}`)}return c.data}function A(n){let r=[];for(let[o,t]of Object.entries(n.agents)){if(!l(t.workspace)){r.push(`Agent "${o}": workspace not found at ${t.workspace}`);continue}if(t.tier==="claude-code"){let c=d(t.workspace,".claude");l(c)||r.push(`Agent "${o}": no .claude/ directory in workspace ${t.workspace}. Claude Code native features (hooks, MCP, skills) won't be available.`)}let a=t.provider||"claude",i=n.providers[a];t.tier!=="claude-code"&&(!i||!i.apiKey)&&r.push(`Agent "${o}": provider "${a}" has no API key configured. Set providers.${a}.apiKey in config or use tier "claude-code" for subscription.`)}for(let[o,t]of Object.entries(n.crons))n.agents[t.agent]||r.push(`Cron "${o}": references unknown agent "${t.agent}"`);if(n.channels.telegram.enabled)for(let[o,t]of Object.entries(n.channels.telegram.accounts))n.agents[t.agentBinding]||r.push(`Telegram account "${o}": references unknown agent "${t.agentBinding}"`);return r}export{j as a,$ as b,A as c};
6
- //# sourceMappingURL=chunk-BHDLKX3G.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/daemon/config.ts"],"sourcesContent":["import { z } from \"zod\"\nimport { readFileSync, existsSync } from \"fs\"\nimport { resolve } from \"path\"\n\n/**\n * Load .env file into process.env (simple, no dependency).\n */\nfunction loadDotEnv(dir: string): void {\n const envPath = resolve(dir, \".env\")\n if (!existsSync(envPath)) return\n\n const content = readFileSync(envPath, \"utf-8\")\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(\"#\")) continue\n const eqIdx = trimmed.indexOf(\"=\")\n if (eqIdx === -1) continue\n const key = trimmed.slice(0, eqIdx).trim()\n const value = trimmed.slice(eqIdx + 1).trim()\n if (!process.env[key]) {\n process.env[key] = value\n }\n }\n}\n\n// --- Daemon configuration schema & loader ---\n\nconst providerConfigSchema = z.object({\n apiKey: z.string().optional(),\n defaultModel: z.string().optional(),\n baseUrl: z.string().optional(),\n})\n\nconst agentConfigSchema = z.object({\n name: z.string(),\n workspace: z.string(),\n tier: z.enum([\"claude-code\", \"sdk\", \"orchestrator\"]).default(\"claude-code\"),\n provider: z.string().optional(),\n model: z.string().optional(),\n systemPrompt: z.string().optional(),\n mentions: z.array(z.string()).default([]),\n maxConcurrent: z.number().default(1),\n permissionMode: z.string().default(\"default\"),\n queueMode: z.enum([\"collect\", \"followup\", \"drop\"]).default(\"collect\"),\n heartbeat: z.object({\n enabled: z.boolean().default(false),\n intervalMinutes: z.number().default(30),\n prompt: z.string().default(\"Check inbox, pending tasks, and system health. Report anything that needs attention.\"),\n channel: z.string().default(\"heartbeat\"),\n }).default({}),\n})\n\nconst telegramAccountSchema = z.object({\n token: z.string(),\n agentBinding: z.string(),\n})\n\nconst channelsConfigSchema = z.object({\n telegram: z.object({\n enabled: z.boolean().default(false),\n accounts: z.record(z.string(), telegramAccountSchema).default({}),\n policy: z.object({\n dm: z.enum([\"pair\", \"block\"]).default(\"pair\"),\n group: z.enum([\"mention-required\", \"all\"]).default(\"mention-required\"),\n }).default({}),\n }).default({}),\n whatsapp: z.object({\n enabled: z.boolean().default(false),\n sessionDir: z.string().default(\".agentx/whatsapp-sessions\"),\n defaultAgent: z.string().optional(),\n allowFrom: z.array(z.string()).optional(),\n routes: z.array(z.object({\n contact: z.string().optional(),\n group: z.string().optional(),\n agent: z.string(),\n })).default([]),\n }).default({}),\n discord: z.object({\n enabled: z.boolean().default(false),\n token: z.string().optional(),\n agentBinding: z.string().optional(),\n }).default({}),\n gitlab: z.object({\n enabled: z.boolean().default(false),\n webhookPort: z.number().default(18810),\n webhookSecret: z.string().optional(),\n host: z.string().default(\"https://gitlab.com\"),\n token: z.string().optional(),\n routes: z.array(z.object({\n project: z.string(),\n agent: z.string(),\n })).default([]),\n agentMappings: z.array(z.object({\n agentId: z.string(),\n gitlabUsernames: z.array(z.string()).default([]),\n keywords: z.array(z.string()).default([]),\n token: z.string().optional(),\n })).default([]),\n }).default({}),\n})\n\nconst cronJobSchema = z.object({\n enabled: z.boolean().default(true),\n schedule: z.string(),\n timezone: z.string().default(\"UTC\"),\n agent: z.string(),\n prompt: z.string(),\n timeout: z.number().default(600),\n model: z.string().optional(),\n onError: z.enum([\"log\", \"notify\", \"disable\"]).default(\"log\"),\n notify: z.object({\n channel: z.string(),\n chatId: z.string(),\n accountId: z.string().optional(),\n }).optional(),\n})\n\nconst meshPeerSchema = z.object({\n url: z.string(),\n name: z.string(),\n token: z.string().optional(),\n})\n\nconst meshConfigSchema = z.object({\n enabled: z.boolean().default(false),\n peers: z.array(meshPeerSchema).default([]),\n discovery: z.enum([\"static\", \"mdns\"]).default(\"static\"),\n healthCheck: z.object({\n interval: z.number().default(60),\n timeout: z.number().default(10),\n }).default({}),\n})\n\nexport const daemonConfigSchema = z.object({\n node: z.object({\n id: z.string(),\n name: z.string(),\n bind: z.string().default(\"127.0.0.1:18800\"),\n }),\n providers: z.record(z.string(), providerConfigSchema).default({}),\n agents: z.record(z.string(), agentConfigSchema).default({}),\n channels: channelsConfigSchema.default({}),\n crons: z.record(z.string(), cronJobSchema).default({}),\n mesh: meshConfigSchema.default({}),\n})\n\nexport type DaemonConfig = z.infer<typeof daemonConfigSchema>\nexport type AgentDef = z.infer<typeof agentConfigSchema>\nexport type CronJobDef = z.infer<typeof cronJobSchema>\nexport type MeshPeer = z.infer<typeof meshPeerSchema>\n\n/**\n * Expand environment variables in strings: ${VAR_NAME} -> process.env.VAR_NAME\n */\nfunction expandEnvVars(obj: unknown): unknown {\n if (typeof obj === \"string\") {\n return obj.replace(/\\$\\{(\\w+)\\}/g, (_match, name) => process.env[name] || \"\")\n }\n if (Array.isArray(obj)) {\n return obj.map(expandEnvVars)\n }\n if (obj !== null && typeof obj === \"object\") {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[key] = expandEnvVars(value)\n }\n return result\n }\n return obj\n}\n\n/**\n * Load daemon config from agentx.json, with env var expansion and validation.\n */\nexport function loadDaemonConfig(configPath?: string): DaemonConfig {\n const paths = configPath\n ? [configPath]\n : [\n resolve(process.cwd(), \"agentx.json\"),\n resolve(process.cwd(), \".agentx/config.json\"),\n ]\n\n // Load .env from same directory as config search\n loadDotEnv(process.cwd())\n\n let raw: string | undefined\n let foundPath: string | undefined\n\n for (const p of paths) {\n if (existsSync(p)) {\n raw = readFileSync(p, \"utf-8\")\n foundPath = p\n break\n }\n }\n\n if (!raw || !foundPath) {\n throw new Error(\n `No config found. Create agentx.json or .agentx/config.json\\n` +\n `Searched: ${paths.join(\", \")}`\n )\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (e: any) {\n throw new Error(`Invalid JSON in ${foundPath}: ${e.message}`)\n }\n\n // Expand environment variables\n const expanded = expandEnvVars(parsed)\n\n // Validate\n const result = daemonConfigSchema.safeParse(expanded)\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\")\n throw new Error(`Config validation failed (${foundPath}):\\n${issues}`)\n }\n\n return result.data\n}\n\n/**\n * Validate agent workspace directories exist and have .claude/ setup.\n */\nexport function validateWorkspaces(config: DaemonConfig): string[] {\n const warnings: string[] = []\n\n for (const [id, agent] of Object.entries(config.agents)) {\n if (!existsSync(agent.workspace)) {\n warnings.push(`Agent \"${id}\": workspace not found at ${agent.workspace}`)\n continue\n }\n\n if (agent.tier === \"claude-code\") {\n const claudeDir = resolve(agent.workspace, \".claude\")\n if (!existsSync(claudeDir)) {\n warnings.push(\n `Agent \"${id}\": no .claude/ directory in workspace ${agent.workspace}. ` +\n `Claude Code native features (hooks, MCP, skills) won't be available.`\n )\n }\n }\n\n // Check provider availability\n const providerName = agent.provider || \"claude\"\n const providerConfig = config.providers[providerName]\n if (agent.tier !== \"claude-code\" && (!providerConfig || !providerConfig.apiKey)) {\n warnings.push(\n `Agent \"${id}\": provider \"${providerName}\" has no API key configured. ` +\n `Set providers.${providerName}.apiKey in config or use tier \"claude-code\" for subscription.`\n )\n }\n }\n\n // Validate cron agent bindings\n for (const [id, cron] of Object.entries(config.crons)) {\n if (!config.agents[cron.agent]) {\n warnings.push(`Cron \"${id}\": references unknown agent \"${cron.agent}\"`)\n }\n }\n\n // Validate channel agent bindings\n if (config.channels.telegram.enabled) {\n for (const [name, account] of Object.entries(config.channels.telegram.accounts)) {\n if (!config.agents[account.agentBinding]) {\n warnings.push(\n `Telegram account \"${name}\": references unknown agent \"${account.agentBinding}\"`\n )\n }\n }\n }\n\n return warnings\n}\n"],"mappings":"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","names":["z","readFileSync","existsSync","resolve","loadDotEnv","dir","envPath","content","line","trimmed","eqIdx","key","value","providerConfigSchema","agentConfigSchema","telegramAccountSchema","channelsConfigSchema","cronJobSchema","meshPeerSchema","meshConfigSchema","daemonConfigSchema","expandEnvVars","obj","_match","name","result","loadDaemonConfig","configPath","paths","raw","foundPath","p","parsed","e","expanded","issues","i","validateWorkspaces","config","warnings","id","agent","claudeDir","providerName","providerConfig","cron","account"]}
@@ -1,12 +0,0 @@
1
- import{a as c,b,d as w}from"./chunk-M7HKBG3V.js";import{e as m}from"./chunk-DSYKYZMT.js";import{z as l}from"zod";var d=["pre:generate","post:generate","pre:file-write","post:file-write","pre:prompt","post:response","pre:command","on:error","pre:tool-call","post:tool-call","pre:channel-message","post:channel-message","pre:a2a-task","pre:cron-run","post:cron-run"],H=["pre:generate","pre:file-write","pre:prompt","post:response","pre:command","pre:tool-call","pre:channel-message","post:channel-message","pre:a2a-task","pre:cron-run"],v=l.object({name:l.string(),type:l.enum(["command","prompt","script"]),command:l.string().optional(),prompt:l.string().optional(),provider:l.enum(["claude-code","claude","openai","ollama","custom"]).optional(),model:l.string().optional(),script:l.string().optional(),priority:l.number().default(100),enabled:l.boolean().default(!0)});var x={"claude-sonnet":{input:3,output:15},"claude-opus":{input:15,output:75},"claude-haiku":{input:.25,output:1.25}};function T(i){let o=i.toLowerCase();return o.includes("opus")?"claude-opus":o.includes("haiku")?"claude-haiku":"claude-sonnet"}var h=class{steps=[];models=new Map;recordStep(o,e,t,r){let n=T(e),s=x[n]||x["claude-sonnet"],p=t/1e6*s.input+r/1e6*s.output;this.steps.push({step:o,model:e,inputTokens:t,outputTokens:r,cost:p,timestamp:Date.now()});let a=this.models.get(e)||{inputTokens:0,outputTokens:0,cost:0,steps:0};a.inputTokens+=t,a.outputTokens+=r,a.cost+=p,a.steps++,this.models.set(e,a)}getSummary(){let o=0,e=0,t=0;for(let n of this.steps)o+=n.inputTokens,e+=n.outputTokens,t+=n.cost;let r={};for(let[n,s]of this.models)r[n]={...s};return{totalInputTokens:o,totalOutputTokens:e,totalTokens:o+e,totalCost:t,steps:[...this.steps],models:r}}reset(){this.steps=[],this.models.clear()}},E=new h;function C(i,o){let e=[];if(e.push(`# Session: ${i.id}`),e.push(""),e.push(`- **Created**: ${i.createdAt}`),e.push(`- **Updated**: ${i.updatedAt}`),e.push(`- **CWD**: ${i.cwd}`),e.push(`- **Messages**: ${i.messages.length}`),e.push(`- **Tokens**: ${i.tokensUsed.toLocaleString()}`),e.push(""),i.filesGenerated.length){e.push("## Files Generated"),e.push("");for(let t of i.filesGenerated)e.push(`- \`${t}\``);e.push("")}if(i.messages.length){e.push("## Conversation"),e.push("");for(let t of i.messages){if(t.role==="system")continue;let r=t.role==="user"?"**User**":"**Assistant**";e.push(`### ${r}`),e.push(""),t.role,e.push(t.content),e.push("")}}if(o){if(e.push("## Cost Summary"),e.push(""),e.push(`- **Total tokens**: ${o.totalTokens.toLocaleString()}`),e.push(` - Input: ${o.totalInputTokens.toLocaleString()}`),e.push(` - Output: ${o.totalOutputTokens.toLocaleString()}`),e.push(`- **Total cost**: $${o.totalCost.toFixed(4)}`),e.push(""),Object.keys(o.models).length){e.push("### Per Model"),e.push(""),e.push("| Model | Input | Output | Cost | Steps |"),e.push("|-------|-------|--------|------|-------|");for(let[t,r]of Object.entries(o.models))e.push(`| ${t} | ${r.inputTokens.toLocaleString()} | ${r.outputTokens.toLocaleString()} | $${r.cost.toFixed(4)} | ${r.steps} |`);e.push("")}if(o.steps.length){e.push("### Per Step"),e.push(""),e.push("| Step | Model | Input | Output | Cost |"),e.push("|------|-------|-------|--------|------|");for(let t of o.steps)e.push(`| ${t.step} | ${t.model} | ${t.inputTokens.toLocaleString()} | ${t.outputTokens.toLocaleString()} | $${t.cost.toFixed(4)} |`);e.push("")}}return e.join(`
2
- `)}import{execa as O}from"execa";var k=class{hooks=new Map;register(o,e){if(!e.enabled)return;let t=this.createHandler(e),r={event:o,definition:e,handler:t},n=this.hooks.get(o)||[];n.push(r),n.sort((s,p)=>s.definition.priority-p.definition.priority),this.hooks.set(o,n)}async execute(o,e){let t=this.hooks.get(o);if(!t?.length)return{};let r=H.includes(o),n={};for(let s of t){let p=Date.now();try{let a=await s.handler({...e,...n}),u=Date.now()-p;if(a.modified&&(n={...n,...a.modified}),r&&a.blocked)return m.hook(s.definition.name,u,"blocked"),{blocked:!0,message:a.message||`Blocked by hook: ${s.definition.name}`,modified:n};m.hook(s.definition.name,u,"ok")}catch(a){let u=Date.now()-p;if(m.hook(s.definition.name,u,`error: ${a.message}`),c.warn(`Hook "${s.definition.name}" failed: ${a.message}`),r)return{blocked:!0,message:`Hook "${s.definition.name}" errored: ${a.message}`}}}return{modified:Object.keys(n).length?n:void 0}}has(o){return!!this.hooks.get(o)?.length}clear(){this.hooks.clear()}createHandler(o){switch(o.type){case"command":return this.createCommandHandler(o);case"script":return this.createScriptHandler(o);case"prompt":return this.createPromptHandler(o);default:throw new Error(`Unknown hook type: ${o.type}`)}}createCommandHandler(o){return async e=>{if(!o.command)return{};let t=o.command;t=t.replace(/\{\{(\w+)\}\}/g,(n,s)=>String(e[s]??""));let r=await O("sh",["-c",t],{cwd:e.cwd||process.cwd(),reject:!1,timeout:6e4,env:process.env});return r.exitCode!==0?{blocked:!0,message:r.stderr||r.stdout||`Command hook "${o.name}" failed`}:{}}}createScriptHandler(o){return async e=>{if(!o.script)return{};let r=await import(o.script.startsWith("/")?o.script:`${e.cwd||process.cwd()}/${o.script}`),n=r.default||r.handler||r;return typeof n=="function"?await n(e):{}}}createPromptHandler(o){return async e=>{if(!o.prompt)return{};let t=o.provider||b()?.provider||"claude-code",r=w();if(!r&&t!=="claude-code")return c.warn(`Prompt hook "${o.name}" skipped: no credentials available for provider "${t}"`),{};try{let{createProvider:n}=await import("./providers-G3WZ4RVJ.js"),s=n(t,r?.token),p=o.prompt;p=p.replace(/\{\{(\w+)\}\}/g,(M,$)=>String(e[$]??""));let a=`You are a hook validator for agentx. Analyze the following context and respond with ONLY a JSON object (no markdown, no code fences).
3
-
4
- Response format:
5
- {"action": "allow", "message": "optional explanation"}
6
- OR
7
- {"action": "block", "message": "reason for blocking"}
8
- OR
9
- {"action": "allow", "message": "optional", "modified": {"key": "new value"}}
10
-
11
- The "modified" field is optional and can contain updated values to pass forward.`,y=(await s.generate([{role:"system",content:a},{role:"user",content:p}],{model:o.model,maxTokens:1024})).content.trim().match(/\{[\s\S]*\}/);if(!y)return c.warn(`Prompt hook "${o.name}": LLM response was not valid JSON, allowing`),{};let f=JSON.parse(y[0]);return f.action==="block"?{blocked:!0,message:f.message||`Blocked by prompt hook: ${o.name}`}:f.modified?{modified:f.modified}:{}}catch(n){return c.warn(`Prompt hook "${o.name}" failed: ${n.message}`),{}}}}};import{existsSync as S,readFileSync as R,readdirSync as D}from"fs";import g from"path";function U(i,o){j(i,o),N(i,o)}function j(i,o){let e=g.join(i,"agentx.config.json");if(S(e))try{let t=JSON.parse(R(e,"utf8"));if(!t.hooks)return;for(let[r,n]of Object.entries(t.hooks)){if(!d.includes(r)){c.warn(`Unknown hook event in config: ${r}`);continue}let s=r;if(Array.isArray(n))for(let p of n)try{let a=v.parse(p);o.register(s,a)}catch(a){c.warn(`Invalid hook definition for ${s}: ${a.message}`)}}}catch(t){c.warn(`Failed to load hooks from config: ${t.message}`)}}function N(i,o){let e=g.join(i,".agentx","hooks");if(S(e))try{let t=D(e).filter(r=>r.endsWith(".ts")||r.endsWith(".js")||r.endsWith(".mjs"));for(let r of t){let n=r.replace(/\.(ts|js|mjs)$/,"").split(".");if(n.length<2){c.warn(`Hook file "${r}" should be named <event>.<name>.<ext>`);continue}let s=n[0],p=n.slice(1).join("."),a=s.replace(/-/g,":");if(!d.includes(a)){let u=s.replace("-",":");if(!d.includes(u)){c.warn(`Unknown hook event in filename: ${r}`);continue}o.register(u,{name:p,type:"script",script:g.join(e,r),priority:100,enabled:!0});continue}o.register(a,{name:p,type:"script",script:g.join(e,r),priority:100,enabled:!0})}}catch(t){c.warn(`Failed to load hooks from directory: ${t.message}`)}}var se=new k;export{d as a,H as b,h as c,E as d,C as e,k as f,U as g,se as h};
12
- //# sourceMappingURL=chunk-CJ45Y2IR.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hooks/types.ts","../src/observability/tracker.ts","../src/observability/export.ts","../src/hooks/registry.ts","../src/hooks/loader.ts","../src/hooks/index.ts"],"sourcesContent":["import { z } from \"zod\"\n\n// --- Hook system types ---\n\nexport const HOOK_EVENTS = [\n \"pre:generate\",\n \"post:generate\",\n \"pre:file-write\",\n \"post:file-write\",\n \"pre:prompt\",\n \"post:response\",\n \"pre:command\",\n \"on:error\",\n \"pre:tool-call\",\n \"post:tool-call\",\n // Daemon events\n \"pre:channel-message\",\n \"post:channel-message\",\n \"pre:a2a-task\",\n \"pre:cron-run\",\n \"post:cron-run\",\n] as const\n\nexport type HookEvent = (typeof HOOK_EVENTS)[number]\n\n// Which hooks can block (return { blocked: true } to cancel the operation)\nexport const BLOCKING_EVENTS: HookEvent[] = [\n \"pre:generate\",\n \"pre:file-write\",\n \"pre:prompt\",\n \"post:response\",\n \"pre:command\",\n \"pre:tool-call\",\n // Daemon blocking events\n \"pre:channel-message\",\n \"post:channel-message\",\n \"pre:a2a-task\",\n \"pre:cron-run\",\n]\n\nexport type HookType = \"command\" | \"prompt\" | \"script\"\n\nexport const hookDefinitionSchema = z.object({\n name: z.string(),\n type: z.enum([\"command\", \"prompt\", \"script\"]),\n // For \"command\" type: shell command with {{variable}} interpolation\n command: z.string().optional(),\n // For \"prompt\" type: LLM prompt template\n prompt: z.string().optional(),\n // For \"prompt\" type: override provider/model for this hook\n provider: z.enum([\"claude-code\", \"claude\", \"openai\", \"ollama\", \"custom\"]).optional(),\n model: z.string().optional(),\n // For \"script\" type: path to JS/TS file exporting a handler\n script: z.string().optional(),\n // Hook priority (lower runs first, default 100)\n priority: z.number().default(100),\n // Whether this hook is enabled\n enabled: z.boolean().default(true),\n})\n\nexport type HookDefinition = z.infer<typeof hookDefinitionSchema>\n\nexport interface HookContext {\n event: HookEvent\n // Data varies by event\n task?: string\n file?: string\n fileContent?: string\n content?: string\n command?: string\n error?: Error\n cwd?: string\n [key: string]: unknown\n}\n\nexport interface HookResult {\n // If true, the operation is blocked/cancelled\n blocked?: boolean\n // Optional message explaining why it was blocked\n message?: string\n // Modified data to pass forward (e.g., modified file content)\n modified?: Record<string, unknown>\n}\n\nexport type HookHandler = (context: HookContext) => Promise<HookResult>\n","// --- Usage tracking: tokens, cost, per-step and per-model breakdown ---\n\nexport interface StepUsage {\n step: number\n model: string\n inputTokens: number\n outputTokens: number\n cost: number\n timestamp: number\n}\n\nexport interface ModelUsage {\n inputTokens: number\n outputTokens: number\n cost: number\n steps: number\n}\n\nexport interface UsageSummary {\n totalInputTokens: number\n totalOutputTokens: number\n totalTokens: number\n totalCost: number\n steps: StepUsage[]\n models: Record<string, ModelUsage>\n}\n\n// Cost per million tokens (input / output)\nconst MODEL_PRICING: Record<string, { input: number; output: number }> = {\n \"claude-sonnet\": { input: 3, output: 15 },\n \"claude-opus\": { input: 15, output: 75 },\n \"claude-haiku\": { input: 0.25, output: 1.25 },\n}\n\nfunction getModelFamily(model: string): string {\n const lower = model.toLowerCase()\n if (lower.includes(\"opus\")) return \"claude-opus\"\n if (lower.includes(\"haiku\")) return \"claude-haiku\"\n return \"claude-sonnet\" // default\n}\n\nexport class UsageTracker {\n private steps: StepUsage[] = []\n private models: Map<string, ModelUsage> = new Map()\n\n recordStep(\n step: number,\n model: string,\n inputTokens: number,\n outputTokens: number\n ): void {\n const family = getModelFamily(model)\n const pricing = MODEL_PRICING[family] || MODEL_PRICING[\"claude-sonnet\"]\n const cost =\n (inputTokens / 1_000_000) * pricing.input +\n (outputTokens / 1_000_000) * pricing.output\n\n this.steps.push({\n step,\n model,\n inputTokens,\n outputTokens,\n cost,\n timestamp: Date.now(),\n })\n\n const existing = this.models.get(model) || {\n inputTokens: 0,\n outputTokens: 0,\n cost: 0,\n steps: 0,\n }\n existing.inputTokens += inputTokens\n existing.outputTokens += outputTokens\n existing.cost += cost\n existing.steps++\n this.models.set(model, existing)\n }\n\n getSummary(): UsageSummary {\n let totalInputTokens = 0\n let totalOutputTokens = 0\n let totalCost = 0\n\n for (const step of this.steps) {\n totalInputTokens += step.inputTokens\n totalOutputTokens += step.outputTokens\n totalCost += step.cost\n }\n\n const models: Record<string, ModelUsage> = {}\n for (const [name, usage] of this.models) {\n models[name] = { ...usage }\n }\n\n return {\n totalInputTokens,\n totalOutputTokens,\n totalTokens: totalInputTokens + totalOutputTokens,\n totalCost,\n steps: [...this.steps],\n models,\n }\n }\n\n reset(): void {\n this.steps = []\n this.models.clear()\n }\n}\n\nexport const globalTracker = new UsageTracker()\n","// --- Session export: convert a session to readable markdown ---\n\nimport type { Session } from \"@/repl/session\"\nimport type { UsageSummary } from \"./tracker\"\n\nexport function exportSession(session: Session, usage?: UsageSummary): string {\n const lines: string[] = []\n\n // Header\n lines.push(`# Session: ${session.id}`)\n lines.push(\"\")\n lines.push(`- **Created**: ${session.createdAt}`)\n lines.push(`- **Updated**: ${session.updatedAt}`)\n lines.push(`- **CWD**: ${session.cwd}`)\n lines.push(`- **Messages**: ${session.messages.length}`)\n lines.push(`- **Tokens**: ${session.tokensUsed.toLocaleString()}`)\n lines.push(\"\")\n\n // Files generated\n if (session.filesGenerated.length) {\n lines.push(\"## Files Generated\")\n lines.push(\"\")\n for (const file of session.filesGenerated) {\n lines.push(`- \\`${file}\\``)\n }\n lines.push(\"\")\n }\n\n // Conversation\n if (session.messages.length) {\n lines.push(\"## Conversation\")\n lines.push(\"\")\n for (const msg of session.messages) {\n if (msg.role === \"system\") continue\n const label = msg.role === \"user\" ? \"**User**\" : \"**Assistant**\"\n lines.push(`### ${label}`)\n lines.push(\"\")\n if (msg.role === \"assistant\") {\n lines.push(msg.content)\n } else {\n lines.push(msg.content)\n }\n lines.push(\"\")\n }\n }\n\n // Cost summary\n if (usage) {\n lines.push(\"## Cost Summary\")\n lines.push(\"\")\n lines.push(`- **Total tokens**: ${usage.totalTokens.toLocaleString()}`)\n lines.push(` - Input: ${usage.totalInputTokens.toLocaleString()}`)\n lines.push(` - Output: ${usage.totalOutputTokens.toLocaleString()}`)\n lines.push(`- **Total cost**: $${usage.totalCost.toFixed(4)}`)\n lines.push(\"\")\n\n if (Object.keys(usage.models).length) {\n lines.push(\"### Per Model\")\n lines.push(\"\")\n lines.push(\"| Model | Input | Output | Cost | Steps |\")\n lines.push(\"|-------|-------|--------|------|-------|\")\n for (const [model, mu] of Object.entries(usage.models)) {\n lines.push(\n `| ${model} | ${mu.inputTokens.toLocaleString()} | ${mu.outputTokens.toLocaleString()} | $${mu.cost.toFixed(4)} | ${mu.steps} |`\n )\n }\n lines.push(\"\")\n }\n\n if (usage.steps.length) {\n lines.push(\"### Per Step\")\n lines.push(\"\")\n lines.push(\"| Step | Model | Input | Output | Cost |\")\n lines.push(\"|------|-------|-------|--------|------|\")\n for (const step of usage.steps) {\n lines.push(\n `| ${step.step} | ${step.model} | ${step.inputTokens.toLocaleString()} | ${step.outputTokens.toLocaleString()} | $${step.cost.toFixed(4)} |`\n )\n }\n lines.push(\"\")\n }\n }\n\n return lines.join(\"\\n\")\n}\n","import { execa } from \"execa\"\nimport type { HookEvent, HookDefinition, HookContext, HookResult, HookHandler } from \"./types\"\nimport { BLOCKING_EVENTS } from \"./types\"\nimport { logger } from \"@/utils/logger\"\nimport { debug } from \"@/observability\"\nimport { loadAuthConfig, resolveToken } from \"@/utils/auth-store\"\n\n// --- Hook Registry: registration, priority ordering, execution ---\n\ninterface RegisteredHook {\n event: HookEvent\n definition: HookDefinition\n handler: HookHandler\n}\n\nexport class HookRegistry {\n private hooks: Map<HookEvent, RegisteredHook[]> = new Map()\n\n /**\n * Register a hook for an event.\n */\n register(event: HookEvent, definition: HookDefinition): void {\n if (!definition.enabled) return\n\n const handler = this.createHandler(definition)\n const entry: RegisteredHook = { event, definition, handler }\n\n const existing = this.hooks.get(event) || []\n existing.push(entry)\n // Sort by priority (lower number = runs first)\n existing.sort((a, b) => a.definition.priority - b.definition.priority)\n this.hooks.set(event, existing)\n }\n\n /**\n * Execute all hooks for an event. Returns combined result.\n * For blocking events, stops at the first hook that returns { blocked: true }.\n */\n async execute(event: HookEvent, context: HookContext): Promise<HookResult> {\n const registered = this.hooks.get(event)\n if (!registered?.length) {\n return {}\n }\n\n const canBlock = BLOCKING_EVENTS.includes(event)\n let combinedModified: Record<string, unknown> = {}\n\n for (const hook of registered) {\n const start = Date.now()\n try {\n const result = await hook.handler({ ...context, ...combinedModified })\n const duration = Date.now() - start\n\n if (result.modified) {\n combinedModified = { ...combinedModified, ...result.modified }\n }\n\n if (canBlock && result.blocked) {\n debug.hook(hook.definition.name, duration, \"blocked\")\n return {\n blocked: true,\n message: result.message || `Blocked by hook: ${hook.definition.name}`,\n modified: combinedModified,\n }\n }\n\n debug.hook(hook.definition.name, duration, \"ok\")\n } catch (error: any) {\n const duration = Date.now() - start\n debug.hook(hook.definition.name, duration, `error: ${error.message}`)\n logger.warn(`Hook \"${hook.definition.name}\" failed: ${error.message}`)\n // Non-blocking hooks swallow errors; blocking hooks propagate\n if (canBlock) {\n return {\n blocked: true,\n message: `Hook \"${hook.definition.name}\" errored: ${error.message}`,\n }\n }\n }\n }\n\n return { modified: Object.keys(combinedModified).length ? combinedModified : undefined }\n }\n\n /**\n * Check if any hooks are registered for an event.\n */\n has(event: HookEvent): boolean {\n const registered = this.hooks.get(event)\n return !!registered?.length\n }\n\n /**\n * Clear all hooks (useful for testing).\n */\n clear(): void {\n this.hooks.clear()\n }\n\n /**\n * Create a HookHandler from a HookDefinition.\n */\n private createHandler(definition: HookDefinition): HookHandler {\n switch (definition.type) {\n case \"command\":\n return this.createCommandHandler(definition)\n case \"script\":\n return this.createScriptHandler(definition)\n case \"prompt\":\n return this.createPromptHandler(definition)\n default:\n throw new Error(`Unknown hook type: ${definition.type}`)\n }\n }\n\n /**\n * Command hook: runs a shell command with {{variable}} interpolation.\n * Exit code 0 = success, non-zero = blocked (for blocking events).\n */\n private createCommandHandler(definition: HookDefinition): HookHandler {\n return async (context: HookContext): Promise<HookResult> => {\n if (!definition.command) {\n return {}\n }\n\n // Interpolate {{variable}} placeholders\n let cmd = definition.command\n cmd = cmd.replace(/\\{\\{(\\w+)\\}\\}/g, (_match, key) => {\n return String(context[key] ?? \"\")\n })\n\n const result = await execa(\"sh\", [\"-c\", cmd], {\n cwd: context.cwd || process.cwd(),\n reject: false,\n timeout: 60_000,\n env: process.env,\n })\n\n if (result.exitCode !== 0) {\n return {\n blocked: true,\n message: result.stderr || result.stdout || `Command hook \"${definition.name}\" failed`,\n }\n }\n\n return {}\n }\n }\n\n /**\n * Script hook: imports and runs a JS/TS module that exports a handler function.\n */\n private createScriptHandler(definition: HookDefinition): HookHandler {\n return async (context: HookContext): Promise<HookResult> => {\n if (!definition.script) {\n return {}\n }\n\n const scriptPath = definition.script.startsWith(\"/\")\n ? definition.script\n : `${context.cwd || process.cwd()}/${definition.script}`\n\n const mod = await import(scriptPath)\n const handler = mod.default || mod.handler || mod\n\n if (typeof handler === \"function\") {\n return await handler(context)\n }\n\n return {}\n }\n }\n\n /**\n * Prompt hook: single-turn LLM call that can block or modify the operation.\n * The prompt template supports {{variable}} interpolation from hook context.\n * The LLM must respond with JSON: { \"action\": \"allow\"|\"block\", \"message\": \"...\", \"modified\": {...} }\n */\n private createPromptHandler(definition: HookDefinition): HookHandler {\n return async (context: HookContext): Promise<HookResult> => {\n if (!definition.prompt) {\n return {}\n }\n\n // Check credentials are available (don't prompt interactively)\n const providerName = definition.provider || loadAuthConfig()?.provider || \"claude-code\"\n const resolved = resolveToken()\n if (!resolved && providerName !== \"claude-code\") {\n logger.warn(\n `Prompt hook \"${definition.name}\" skipped: no credentials available for provider \"${providerName}\"`\n )\n return {}\n }\n\n try {\n // Lazy import to avoid circular deps\n const { createProvider } = await import(\"@/agent/providers\")\n const provider = createProvider(providerName as any, resolved?.token)\n\n // Interpolate {{variable}} placeholders in the prompt template\n let prompt = definition.prompt\n prompt = prompt.replace(/\\{\\{(\\w+)\\}\\}/g, (_match, key) => {\n return String(context[key] ?? \"\")\n })\n\n const systemPrompt = `You are a hook validator for agentx. Analyze the following context and respond with ONLY a JSON object (no markdown, no code fences).\n\nResponse format:\n{\"action\": \"allow\", \"message\": \"optional explanation\"}\nOR\n{\"action\": \"block\", \"message\": \"reason for blocking\"}\nOR\n{\"action\": \"allow\", \"message\": \"optional\", \"modified\": {\"key\": \"new value\"}}\n\nThe \"modified\" field is optional and can contain updated values to pass forward.`\n\n const result = await provider.generate(\n [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: prompt },\n ],\n {\n model: definition.model,\n maxTokens: 1024,\n }\n )\n\n // Parse the LLM response as JSON\n const content = result.content.trim()\n // Try to extract JSON from the response (handle markdown fences)\n const jsonMatch = content.match(/\\{[\\s\\S]*\\}/)\n if (!jsonMatch) {\n logger.warn(`Prompt hook \"${definition.name}\": LLM response was not valid JSON, allowing`)\n return {}\n }\n\n const parsed = JSON.parse(jsonMatch[0])\n\n if (parsed.action === \"block\") {\n return {\n blocked: true,\n message: parsed.message || `Blocked by prompt hook: ${definition.name}`,\n }\n }\n\n if (parsed.modified) {\n return { modified: parsed.modified }\n }\n\n return {}\n } catch (error: any) {\n // Don't block on hook failures — log and continue\n logger.warn(`Prompt hook \"${definition.name}\" failed: ${error.message}`)\n return {}\n }\n }\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"fs\"\nimport path from \"path\"\nimport type { HookEvent, HookDefinition } from \"./types\"\nimport { HOOK_EVENTS, hookDefinitionSchema } from \"./types\"\nimport { HookRegistry } from \"./registry\"\nimport { logger } from \"@/utils/logger\"\n\n// --- Hook Loader: load hooks from config and .agentx/hooks/ ---\n\ninterface HooksConfig {\n hooks?: Partial<Record<HookEvent, HookDefinition[]>>\n}\n\n/**\n * Load hooks from agentx.config.json and .agentx/hooks/ directory.\n */\nexport function loadHooks(cwd: string, registry: HookRegistry): void {\n loadHooksFromConfig(cwd, registry)\n loadHooksFromDirectory(cwd, registry)\n}\n\n/**\n * Load hook definitions from agentx.config.json.\n */\nfunction loadHooksFromConfig(cwd: string, registry: HookRegistry): void {\n const configPath = path.join(cwd, \"agentx.config.json\")\n if (!existsSync(configPath)) return\n\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf8\")) as HooksConfig\n if (!raw.hooks) return\n\n for (const [eventName, definitions] of Object.entries(raw.hooks)) {\n if (!HOOK_EVENTS.includes(eventName as HookEvent)) {\n logger.warn(`Unknown hook event in config: ${eventName}`)\n continue\n }\n\n const event = eventName as HookEvent\n if (!Array.isArray(definitions)) continue\n\n for (const def of definitions) {\n try {\n const parsed = hookDefinitionSchema.parse(def)\n registry.register(event, parsed)\n } catch (error: any) {\n logger.warn(`Invalid hook definition for ${event}: ${error.message}`)\n }\n }\n }\n } catch (error: any) {\n logger.warn(`Failed to load hooks from config: ${error.message}`)\n }\n}\n\n/**\n * Load hook scripts from .agentx/hooks/ directory.\n * Files are named <event>.<name>.ts (e.g., pre-file-write.format.ts).\n */\nfunction loadHooksFromDirectory(cwd: string, registry: HookRegistry): void {\n const hooksDir = path.join(cwd, \".agentx\", \"hooks\")\n if (!existsSync(hooksDir)) return\n\n try {\n const files = readdirSync(hooksDir).filter(\n (f) => f.endsWith(\".ts\") || f.endsWith(\".js\") || f.endsWith(\".mjs\")\n )\n\n for (const file of files) {\n // Parse filename: <event>.<name>.<ext>\n // Event uses dashes in filename: pre-file-write → pre:file-write\n const parts = file.replace(/\\.(ts|js|mjs)$/, \"\").split(\".\")\n if (parts.length < 2) {\n logger.warn(`Hook file \"${file}\" should be named <event>.<name>.<ext>`)\n continue\n }\n\n const eventSlug = parts[0]\n const name = parts.slice(1).join(\".\")\n\n // Convert slug to event name: pre-file-write → pre:file-write\n const eventName = eventSlug.replace(/-/g, \":\") as HookEvent\n if (!HOOK_EVENTS.includes(eventName)) {\n // Try replacing first dash only: pre-generate → pre:generate\n const altEvent = eventSlug.replace(\"-\", \":\") as HookEvent\n if (!HOOK_EVENTS.includes(altEvent)) {\n logger.warn(`Unknown hook event in filename: ${file}`)\n continue\n }\n registry.register(altEvent, {\n name,\n type: \"script\",\n script: path.join(hooksDir, file),\n priority: 100,\n enabled: true,\n })\n continue\n }\n\n registry.register(eventName, {\n name,\n type: \"script\",\n script: path.join(hooksDir, file),\n priority: 100,\n enabled: true,\n })\n }\n } catch (error: any) {\n logger.warn(`Failed to load hooks from directory: ${error.message}`)\n }\n}\n","export { HookRegistry } from \"./registry\"\nexport { loadHooks } from \"./loader\"\nexport type { HookEvent, HookDefinition, HookContext, HookResult, HookHandler } from \"./types\"\nexport { HOOK_EVENTS, BLOCKING_EVENTS } from \"./types\"\n\nimport { HookRegistry } from \"./registry\"\n\n// Singleton hook registry for the CLI process\nexport const globalHooks = new HookRegistry()\n"],"mappings":"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","names":["z","HOOK_EVENTS","BLOCKING_EVENTS","hookDefinitionSchema","MODEL_PRICING","getModelFamily","model","lower","UsageTracker","step","inputTokens","outputTokens","family","pricing","cost","existing","totalInputTokens","totalOutputTokens","totalCost","models","name","usage","globalTracker","exportSession","session","usage","lines","file","msg","label","model","mu","step","execa","HookRegistry","event","definition","handler","entry","existing","a","b","context","registered","canBlock","BLOCKING_EVENTS","combinedModified","hook","start","result","duration","debug","error","logger","cmd","_match","key","execa","mod","providerName","loadAuthConfig","resolved","resolveToken","createProvider","provider","prompt","systemPrompt","jsonMatch","parsed","existsSync","readFileSync","readdirSync","path","loadHooks","cwd","registry","loadHooksFromConfig","loadHooksFromDirectory","configPath","path","existsSync","raw","readFileSync","eventName","definitions","HOOK_EVENTS","logger","event","def","parsed","hookDefinitionSchema","error","hooksDir","files","readdirSync","f","file","parts","eventSlug","name","altEvent","globalHooks","HookRegistry"]}
@@ -1,3 +0,0 @@
1
- import{existsSync as S,promises as v}from"fs";import k from"path";import x from"fast-glob";import{z as l}from"zod";var h=l.object({name:l.string(),description:l.string(),version:l.string().optional(),author:l.string().optional(),tags:l.array(l.string()).optional(),globs:l.array(l.string()).optional(),triggers:l.array(l.object({pattern:l.string(),description:l.string().optional()})).optional()});var L=[".skills",".claude/skills","skills"],d="SKILL.md";async function T(a){let e=[];for(let r of L){let n=k.resolve(a,r);if(!S(n))continue;let c=await x.glob(`**/${d}`,{cwd:n,deep:3});for(let s of c){let t=k.resolve(n,s),i=await w(t);i&&(i.source="local",i.path=t,e.push(i))}}let m=k.resolve(a,d);if(S(m)){let r=await w(m);r&&(r.source="local",r.path=m,e.push(r))}return e}async function w(a){try{let e=await v.readFile(a,"utf8");return F(e)}catch{return null}}function F(a){try{let e=a.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!e)return{frontmatter:{name:"unnamed",description:"No description"},instructions:a.trim(),source:"local"};let[,m,r]=e,n=M(m);return{frontmatter:h.parse(n),instructions:r.trim(),source:"local"}}catch{return null}}function M(a){let e={},m=a.split(`
2
- `),r="",n=!1,c=[];for(let s of m){let t=s.trim();if(!t)continue;if(t.startsWith("- ")&&n){c.push(t.slice(2).trim().replace(/^["']|["']$/g,""));continue}n&&r&&(e[r]=c,n=!1,c=[]);let i=t.match(/^(\w+)\s*:\s*(.*)$/);if(i){let[,p,g]=i;r=p,g.trim()===""?(n=!0,c=[]):e[p]=g.trim().replace(/^["']|["']$/g,"")}}return n&&r&&(e[r]=c),e}function W(a,e,m){let r=[],n=e.toLowerCase(),c=new Set(n.split(/\s+/));for(let s of a){let t=0,i="";if(s.frontmatter.triggers)for(let o of s.frontmatter.triggers)try{new RegExp(o.pattern,"i").test(e)&&(t=Math.max(t,.9),i=`Trigger match: ${o.description||o.pattern}`)}catch{n.includes(o.pattern.toLowerCase())&&(t=Math.max(t,.7),i=`Keyword match: ${o.pattern}`)}if(s.frontmatter.tags){let o=s.frontmatter.tags.filter(f=>c.has(f.toLowerCase())||n.includes(f.toLowerCase()));if(o.length){let f=Math.min(o.length*.3,.8);f>t&&(t=f,i=`Tag match: ${o.join(", ")}`)}}let p=s.frontmatter.name.toLowerCase().split(/[-_\s]+/),g=s.frontmatter.description.toLowerCase().split(/\s+/),y=new Set([...p,...g]),u=[...c].filter(o=>y.has(o)&&o.length>3);if(u.length>0){let o=Math.min(u.length*.2,.6);o>t&&(t=o,i=`Content match: ${u.join(", ")}`)}t>.1&&r.push({skill:s,relevance:t,matchReason:i})}return r.sort((s,t)=>t.relevance-s.relevance)}export{T as a,w as b,F as c,W as d};
3
- //# sourceMappingURL=chunk-FRFR27IN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/agent/skills/loader.ts","../src/agent/skills/types.ts"],"sourcesContent":["import { existsSync, promises as fs } from \"fs\"\nimport path from \"path\"\nimport fg from \"fast-glob\"\nimport { logger } from \"@/utils/logger\"\nimport type { Skill, SkillFrontmatter, SkillMatch } from \"./types\"\nimport { skillFrontmatterSchema } from \"./types\"\n\n// --- Load skills from local files and remote packages ---\n\nconst SKILL_DIRS = [\".skills\", \".claude/skills\", \"skills\"]\nconst SKILL_FILE = \"SKILL.md\"\n\nexport async function loadLocalSkills(cwd: string): Promise<Skill[]> {\n const skills: Skill[] = []\n\n for (const dir of SKILL_DIRS) {\n const skillDir = path.resolve(cwd, dir)\n if (!existsSync(skillDir)) continue\n\n const skillFiles = await fg.glob(`**/${SKILL_FILE}`, {\n cwd: skillDir,\n deep: 3,\n })\n\n for (const file of skillFiles) {\n const fullPath = path.resolve(skillDir, file)\n const skill = await parseSkillFile(fullPath)\n if (skill) {\n skill.source = \"local\"\n skill.path = fullPath\n skills.push(skill)\n }\n }\n }\n\n // Also check for a single SKILL.md at project root\n const rootSkill = path.resolve(cwd, SKILL_FILE)\n if (existsSync(rootSkill)) {\n const skill = await parseSkillFile(rootSkill)\n if (skill) {\n skill.source = \"local\"\n skill.path = rootSkill\n skills.push(skill)\n }\n }\n\n return skills\n}\n\nexport async function parseSkillFile(filePath: string): Promise<Skill | null> {\n try {\n const content = await fs.readFile(filePath, \"utf8\")\n return parseSkillContent(content)\n } catch {\n return null\n }\n}\n\nexport function parseSkillContent(content: string): Skill | null {\n try {\n // Parse YAML frontmatter\n const frontmatterMatch = content.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/)\n\n if (!frontmatterMatch) {\n // No frontmatter - treat entire content as instructions with minimal metadata\n return {\n frontmatter: { name: \"unnamed\", description: \"No description\" },\n instructions: content.trim(),\n source: \"local\",\n }\n }\n\n const [, frontmatterRaw, instructions] = frontmatterMatch\n const frontmatter = parseYamlFrontmatter(frontmatterRaw)\n\n const validated = skillFrontmatterSchema.parse(frontmatter)\n\n return {\n frontmatter: validated,\n instructions: instructions.trim(),\n source: \"local\",\n }\n } catch {\n return null\n }\n}\n\nfunction parseYamlFrontmatter(raw: string): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n const lines = raw.split(\"\\n\")\n\n let currentKey = \"\"\n let inArray = false\n let arrayValues: string[] = []\n\n for (const line of lines) {\n const trimmed = line.trim()\n if (!trimmed) continue\n\n // Array item\n if (trimmed.startsWith(\"- \") && inArray) {\n arrayValues.push(trimmed.slice(2).trim().replace(/^[\"']|[\"']$/g, \"\"))\n continue\n }\n\n // Save previous array if we were in one\n if (inArray && currentKey) {\n result[currentKey] = arrayValues\n inArray = false\n arrayValues = []\n }\n\n // Key-value pair\n const kvMatch = trimmed.match(/^(\\w+)\\s*:\\s*(.*)$/)\n if (kvMatch) {\n const [, key, value] = kvMatch\n currentKey = key\n\n if (value.trim() === \"\") {\n // Could be start of an array or nested object\n inArray = true\n arrayValues = []\n } else {\n // Simple value\n result[key] = value.trim().replace(/^[\"']|[\"']$/g, \"\")\n }\n }\n }\n\n // Save last array if any\n if (inArray && currentKey) {\n result[currentKey] = arrayValues\n }\n\n return result\n}\n\nexport function matchSkillsToTask(\n skills: Skill[],\n taskDescription: string,\n outputType?: string\n): SkillMatch[] {\n const matches: SkillMatch[] = []\n const taskLower = taskDescription.toLowerCase()\n const taskWords = new Set(taskLower.split(/\\s+/))\n\n for (const skill of skills) {\n let relevance = 0\n let matchReason = \"\"\n\n // Check trigger patterns\n if (skill.frontmatter.triggers) {\n for (const trigger of skill.frontmatter.triggers) {\n try {\n const regex = new RegExp(trigger.pattern, \"i\")\n if (regex.test(taskDescription)) {\n relevance = Math.max(relevance, 0.9)\n matchReason = `Trigger match: ${trigger.description || trigger.pattern}`\n }\n } catch {\n // Invalid regex - try simple string match\n if (taskLower.includes(trigger.pattern.toLowerCase())) {\n relevance = Math.max(relevance, 0.7)\n matchReason = `Keyword match: ${trigger.pattern}`\n }\n }\n }\n }\n\n // Check tags overlap\n if (skill.frontmatter.tags) {\n const tagOverlap = skill.frontmatter.tags.filter(\n (tag) => taskWords.has(tag.toLowerCase()) || taskLower.includes(tag.toLowerCase())\n )\n if (tagOverlap.length) {\n const tagRelevance = Math.min(tagOverlap.length * 0.3, 0.8)\n if (tagRelevance > relevance) {\n relevance = tagRelevance\n matchReason = `Tag match: ${tagOverlap.join(\", \")}`\n }\n }\n }\n\n // Check name/description overlap\n const nameWords = skill.frontmatter.name.toLowerCase().split(/[-_\\s]+/)\n const descWords = skill.frontmatter.description.toLowerCase().split(/\\s+/)\n const allSkillWords = new Set([...nameWords, ...descWords])\n\n const overlap = [...taskWords].filter((w) => allSkillWords.has(w) && w.length > 3)\n if (overlap.length > 0) {\n const wordRelevance = Math.min(overlap.length * 0.2, 0.6)\n if (wordRelevance > relevance) {\n relevance = wordRelevance\n matchReason = `Content match: ${overlap.join(\", \")}`\n }\n }\n\n if (relevance > 0.1) {\n matches.push({ skill, relevance, matchReason })\n }\n }\n\n return matches.sort((a, b) => b.relevance - a.relevance)\n}\n","import { z } from \"zod\"\n\n// --- Skill types aligned with skills.sh / Agent Skills spec ---\n\nexport const skillFrontmatterSchema = z.object({\n name: z.string(),\n description: z.string(),\n version: z.string().optional(),\n author: z.string().optional(),\n tags: z.array(z.string()).optional(),\n globs: z.array(z.string()).optional(),\n // When to automatically apply this skill\n triggers: z\n .array(\n z.object({\n pattern: z.string(), // regex or keyword pattern\n description: z.string().optional(),\n })\n )\n .optional(),\n})\n\nexport type SkillFrontmatter = z.infer<typeof skillFrontmatterSchema>\n\nexport interface Skill {\n frontmatter: SkillFrontmatter\n instructions: string // Markdown body\n source: \"local\" | \"remote\" | \"generated\"\n path?: string // Local file path\n packageId?: string // e.g., \"intellectronica/agent-skills\"\n}\n\nexport interface SkillMatch {\n skill: Skill\n relevance: number // 0-1 how relevant to current task\n matchReason: string\n}\n\nexport interface SkillPackage {\n owner: string\n repo: string\n skills: Skill[]\n}\n"],"mappings":"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","names":["existsSync","fs","path","fg","z","skillFrontmatterSchema","SKILL_DIRS","SKILL_FILE","loadLocalSkills","cwd","skills","dir","skillDir","path","existsSync","skillFiles","fg","file","fullPath","skill","parseSkillFile","rootSkill","filePath","content","fs","parseSkillContent","frontmatterMatch","frontmatterRaw","instructions","frontmatter","parseYamlFrontmatter","skillFrontmatterSchema","raw","result","lines","currentKey","inArray","arrayValues","line","trimmed","kvMatch","key","value","matchSkillsToTask","taskDescription","outputType","matches","taskLower","taskWords","relevance","matchReason","trigger","tagOverlap","tag","tagRelevance","nameWords","descWords","allSkillWords","overlap","w","wordRelevance","a","b"]}
@@ -1,136 +0,0 @@
1
- import{a as I,b as C}from"./chunk-X32247GM.js";import{a as F}from"./chunk-34UAFPK4.js";import{a as j}from"./chunk-ZRYBSI5G.js";import{execa as oe}from"execa";import{execFile as ae}from"child_process";function U(c,e,t){let s=[];if(c.systemPrompt&&s.push(c.systemPrompt),e.context&&!t){let n=e.context,r=["","[Environment]"],i=n.channel==="gitlab"||n.channel?.startsWith("webhook:"),a=n.channel==="telegram";if(n.channel&&r.push(`Channel: ${n.channel}`),n.group&&r.push(`Group: ${n.group}`),n.sender&&r.push(`Message from: ${n.sender}`),n.myHandle&&r.push(`Your handle on this channel: ${n.myHandle}`),i&&(r.push(""),r.push("[IMPORTANT: You are responding to a GitLab comment/event]"),r.push("- Keep it short \u2014 3-5 lines for the main message. Humans scan, not read"),r.push("- Lead with the result or action, not a narration of what you plan to do"),r.push("- Use <details><summary>Details</summary>\\n\\ncontent\\n</details> for verbose output (logs, full commands, step-by-step)"),r.push("- Do NOT mention Telegram handles \u2014 they don't work on GitLab"),r.push("- Do NOT try to delegate to other agents \u2014 reply directly"),r.push("- Reference issues with #IID and MRs with !IID")),a&&n.peers?.length){r.push(""),r.push("[Team \u2014 other agents you can mention to delegate or collaborate]");for(let o of n.peers){let d=o.handle?` (mention: ${o.handle})`:"",l=o.role?` \u2014 ${o.role}`:"";r.push(`\u2022 ${o.name}${d}${l}`)}r.push(""),r.push("To involve another agent, mention their handle in your response and they will automatically see it and reply.")}s.push(r.join(`
2
- `))}return e.context?.replyToText&&(s.push(""),s.push(`[Replying to]: ${e.context.replyToText}`)),e.context?.mediaPath&&(s.push(""),s.push(`[Attached file: ${e.context.mediaPath}]`),s.push(`[File type: ${e.context.mediaType||"unknown"}]`),e.context.mediaType?.startsWith("image/")?s.push("Please read/view this image file and describe or respond to it."):e.context.mediaType?.startsWith("audio/")?s.push("Please transcribe this audio file and respond to its content."):e.context.mediaType?.startsWith("video/")?s.push("A video file is attached. Describe what you can determine about it."):s.push("Please read this file and respond based on its content.")),t&&(s.push(""),s.push(t)),s.push(""),s.push(e.message),s.join(`
3
- `)}function N(c,e,t,s){let n=["-p",e,"--output-format",t?"stream-json":"json"];return t&&n.push("--verbose"),s&&n.push("--resume",s),c.model&&n.push("--model",c.model),c.permissionMode==="bypassPermissions"&&n.push("--dangerously-skip-permissions"),n}function ce(c){try{let e=JSON.parse(c),t=e.usage?{inputTokens:e.usage.input_tokens||0,outputTokens:e.usage.output_tokens||0,cacheReadTokens:e.usage.cache_read_input_tokens||0,cacheCreateTokens:e.usage.cache_creation_input_tokens||0}:void 0;return{text:e.result||e.content||"",sessionId:e.session_id,usage:t}}catch{return{text:c}}}async function de(c,e,t,s){let n=Date.now(),r=U(c,e,t),i=N(c,r,!1,s);try{let{stdout:a,stderr:o,exitCode:d}=await new Promise((g,m)=>{let h=ae("claude",i,{cwd:c.workspace,timeout:6e5,maxBuffer:10485760,env:{...process.env,HOME:process.env.HOME||"/home/"+(process.env.USER||"user")}},(f,p,w)=>{g({stdout:p||"",stderr:w||"",exitCode:f?f.code??1:0})})});if(!a&&d!==0)return{content:"",error:(o?.trim()||`Claude Code exited with code ${d}`).slice(0,300),duration:Date.now()-n};let l=ce(a);return{content:l.text,duration:Date.now()-n,claudeSessionId:l.sessionId,usage:l.usage}}catch(a){return console.error(`[runtime] execFile threw: ${a.message}`),{content:"",error:a.message||"Claude Code failed",duration:Date.now()-n}}}async function ge(c,e,t,s,n){let r=Date.now(),i=U(c,e,s),a=N(c,i,!0,n),o="";try{let d=oe("claude",a,{cwd:c.workspace,timeout:6e5,reject:!1,env:process.env,buffer:!1});if(d.stdout){let g="";d.stdout.on("data",m=>{g+=m.toString();let h=g.split(`
4
- `);g=h.pop()||"";for(let f of h)if(f.trim())try{let p=JSON.parse(f);if(p.type==="assistant"&&p.message?.content){for(let w of p.message.content)if(w.type==="text"&&w.text){let v=w.text.slice(o.length);v&&(o=w.text,t(v,o))}}if(p.type==="content_block_delta"&&p.delta?.text&&(o+=p.delta.text,t(p.delta.text,o)),p.type==="result"&&p.result){let w=(typeof p.result=="string",p.result);if(typeof w=="string"&&w.length>o.length){let v=w.slice(o.length);o=w,v&&t(v,o)}}}catch{f.trim()&&!f.startsWith("{")&&(o+=f+`
5
- `,t(f+`
6
- `,o))}})}let l=await d;return!o&&l.stdout&&(o=typeof l.stdout=="string"?l.stdout:""),l.exitCode!==0&&!o?{content:"",error:(typeof l.stderr=="string"?l.stderr:"")||`Claude Code exited with code ${l.exitCode}`,duration:Date.now()-r}:{content:o,duration:Date.now()-r}}catch(d){return{content:o||"",error:d.message,duration:Date.now()-r}}}async function le(c,e,t){let s=Date.now();try{let n=await import("@anthropic-ai/claude-agent-sdk"),{query:r}=n,i=c.systemPrompt?`${c.systemPrompt}
7
-
8
- ${e.message}`:e.message,a="",o=r({prompt:i,options:{model:c.model,cwd:c.workspace,permissionMode:"bypassPermissions"}});for await(let d of o)d.type==="result"&&d.subtype==="success"&&(a=d.result||"");return{content:a,duration:Date.now()-s}}catch(n){return{content:"",error:`SDK error: ${n.message}`,duration:Date.now()-s}}}async function ue(c,e,t){let s=Date.now();try{let{generate:n}=await import("./agent-QYQVGKLM.js"),r=c.provider||"claude-code",i=await n({task:e.message,cwd:c.workspace,provider:r,model:c.model,apiKey:t,overwrite:!0,interactive:!1,context7:!1});return{content:i.content||"Done.",tokensUsed:i.tokensUsed,duration:Date.now()-s}}catch(n){return{content:"",error:`Orchestrator error: ${n.message}`,duration:Date.now()-s}}}async function B(c,e,t,s,n,r){switch(c.tier){case"claude-code":return s?ge(c,e,s,n,r):de(c,e,n,r);case"sdk":{let i=c.provider||"claude",a=t[i]?.apiKey;return a?le(c,e,a):{content:"",error:`No API key for provider "${i}". Configure providers.${i}.apiKey`}}case"orchestrator":{let i=c.provider||"claude-code",a=t[i]?.apiKey;return ue(c,e,a)}default:return{content:"",error:`Unknown tier: ${c.tier}`}}}import{readFileSync as H,writeFileSync as he,mkdirSync as me,existsSync as Q,readdirSync as pe}from"fs";import{resolve as O}from"path";var fe=12e3,K=30,ye=15,we="[Compacted conversation summary",W=class{sessionsDir;cache=new Map;constructor(e=process.cwd()){this.sessionsDir=O(e,".agentx/sessions"),Q(this.sessionsDir)||me(this.sessionsDir,{recursive:!0})}sessionKey(e,t,s){let n=new Date().toISOString().slice(0,10);return`${e}:${t}:${s}:${n}`}sessionFile(e){let t=e.replace(/[^a-zA-Z0-9_:-]/g,"_");return O(this.sessionsDir,`${t}.json`)}getSession(e,t,s){let n=this.sessionKey(e,t,s);if(this.cache.has(n))return this.cache.get(n);let r=this.sessionFile(n);if(Q(r))try{let o=JSON.parse(H(r,"utf-8"));return this.cache.set(n,o),o}catch{}let i=new Date().toISOString().slice(0,10),a={id:n,agentId:e,channel:t,chatId:s,day:i,messages:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return this.cache.set(n,a),this.save(a),a}addUserMessage(e,t,s,n,r){let i=this.getSession(e,t,s);i.messages.push({role:"user",name:n,content:r,timestamp:new Date().toISOString()}),this.trim(i),i.updatedAt=new Date().toISOString(),this.save(i)}addAgentMessage(e,t,s,n){let r=this.getSession(e,t,s);r.messages.push({role:"agent",name:e,content:n,timestamp:new Date().toISOString()}),this.trim(r),r.updatedAt=new Date().toISOString(),this.save(r)}getClaudeSessionId(e,t,s){return this.getSession(e,t,s).claudeSessionId}setClaudeSessionId(e,t,s,n){let r=this.getSession(e,t,s);r.claudeSessionId=n,r.updatedAt=new Date().toISOString(),this.save(r)}buildHistoryContext(e,t,s){let n=this.getSession(e,t,s);if(n.messages.length===0)return"";let r=[`[Conversation history for today (${n.day})]`];for(let i of n.messages){let a=i.timestamp.slice(11,16);i.role==="user"?r.push(`[${a}] ${i.name||"User"}: ${i.content}`):r.push(`[${a}] ${i.name||"Agent"}: ${i.content}`)}return r.push("[End of history \u2014 respond to the latest message above]"),r.push(""),r.join(`
9
- `)}isSessionStale(e,t,s){let n=this.getSession(e,t,s);return n.claudeSessionId?Date.now()-new Date(n.updatedAt).getTime()>ye*60*1e3:!1}getCrossSessionSummary(e,t,s){let n=new Date().toISOString().slice(0,10),r=this.sessionKey(e,t,s);try{let i=pe(this.sessionsDir).filter(o=>o.startsWith(e.replace(/[^a-zA-Z0-9_:-]/g,"_"))&&o.includes(n)&&o.endsWith(".json")),a=[];for(let o of i)try{let d=JSON.parse(H(O(this.sessionsDir,o),"utf-8"));if(d.id===r||d.messages.length===0)continue;let l=d.messages.slice(-4),m=!d.chatId.startsWith("-")&&/^\d+$/.test(d.chatId)?"DM":d.chatId,h=l.map(f=>` [${f.timestamp.slice(11,16)}] ${f.name||f.role}: ${f.content.slice(0,200)}`);a.push(`From ${m} (${d.channel}):
10
- ${h.join(`
11
- `)}`)}catch{}return a.length===0?"":["[Cross-chat context \u2014 recent activity from your other conversations today]",...a,"[End cross-chat context \u2014 the user in THIS chat may be referring to actions from above]",""].join(`
12
- `)}catch{return""}}async compactIfNeeded(e,t,s,n){let r=this.getSession(e,t,s),{needsCompaction:i,compactSession:a,applyCompaction:o}=await import("./compaction-E3MQRLTL.js");if(!i(r.messages))return!1;let d=await a(r.messages,e,n);return d.compactedCount===0?!1:(r.messages=o(r.messages,d),r.updatedAt=new Date().toISOString(),delete r.claudeSessionId,this.save(r),!0)}hasCompaction(e,t,s){let n=this.getSession(e,t,s);return n.messages.length>0&&n.messages[0].content.startsWith(we)}clearClaudeSessionId(e,t,s){let n=this.getSession(e,t,s);delete n.claudeSessionId,n.updatedAt=new Date().toISOString(),this.save(n)}trim(e){e.messages.length>K&&(e.messages=e.messages.slice(-K));let t=e.messages.reduce((s,n)=>s+n.content.length,0);for(;t>fe&&e.messages.length>2;){let s=e.messages.shift();t-=s.content.length}}save(e){try{let t=this.sessionFile(e.id);he(t,JSON.stringify(e,null,2))}catch{}}};import{readFileSync as $,writeFileSync as S,appendFileSync as be,existsSync as k,mkdirSync as L,readdirSync as E,statSync as xe}from"fs";import{resolve as y,join as ke,relative as x,dirname as Se}from"path";var A=class{baseDir;rawDir;log;constructor(e=y(process.cwd(),".agentx/wiki"),t=console.error.bind(console,"[wiki]")){this.baseDir=e,this.rawDir=y(e,"raw/entries"),this.log=t,L(this.rawDir,{recursive:!0}),L(y(e,"raw"),{recursive:!0}),this.ensureSchema()}canRead(e,t){return e.access==="public"?!0:t?!!(e.owner===t||e.access==="shared"&&e.sharedWith?.includes(t)):!1}canWrite(e,t){return e.owner===t}addEntry(e){let t=`${e.date}_${e.id}.md`,s=y(this.rawDir,t),n=["---",`id: ${e.id}`,`date: ${e.date}`,`agent: ${e.agentId}`,`source: ${e.source}`];if(e.sourceContext&&n.push(`context: ${e.sourceContext}`),e.meta)for(let[r,i]of Object.entries(e.meta))n.push(`${r}: ${JSON.stringify(i)}`);return n.push("---","",e.content),S(s,n.join(`
13
- `)),this.appendLog("ingest",`${e.id} from ${e.agentId} via ${e.source}`),t}listEntries(e){if(!k(this.rawDir))return[];let t=E(this.rawDir).filter(n=>n.endsWith(".md")).sort(),s=[];for(let n of t){let r=$(y(this.rawDir,n),"utf-8"),i=this.parseEntry(r,n);i&&(e?.agentId&&i.agentId!==e.agentId||e?.after&&i.date<e.after||e?.before&&i.date>e.before||s.push(i))}return s}parseEntry(e,t){let s=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!s)return null;let n=s[1],r=s[2].trim(),i=a=>n.match(new RegExp(`^${a}:\\s*(.+)$`,"m"))?.[1]?.trim()||"";return{id:i("id")||t.replace(".md",""),date:i("date"),agentId:i("agent"),source:i("source"),sourceContext:i("context")||void 0,content:r}}writeArticle(e,t,s,n){let r=this.readArticle(e);if(r&&!this.canWrite(r.meta,n))return this.log(`Permission denied: "${n}" cannot write "${e}" (owner: ${r.meta.owner})`),!1;let i=y(this.baseDir,e);L(Se(i),{recursive:!0});let a=["---",`title: "${t.title}"`,`tags: [${(t.tags||[]).map(d=>`"${d}"`).join(", ")}]`,`owner: ${t.owner}`,`access: ${t.access}`];t.sharedWith?.length&&a.push(`shared_with: [${t.sharedWith.map(d=>`"${d}"`).join(", ")}]`),a.push(`created: ${t.created}`,`last_updated: ${t.lastUpdated}`,`sources: [${t.sources.map(d=>`"${d}"`).join(", ")}]`),a.push("---","",s),S(i,a.join(`
14
- `));let o=r?"update":"create";return this.appendLog(o,`${t.title} [${(t.tags||[]).slice(0,5).join(", ")}] by ${n} at ${e}`),!0}readArticle(e){let t=y(this.baseDir,e);if(!k(t))return null;let s=$(t,"utf-8");return this.parseArticle(s,e)}readArticleAs(e,t){let s=this.readArticle(e);return!s||!this.canRead(s.meta,t)?null:s}parseArticle(e,t){let s=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!s)return null;let n=s[1],r=s[2].trim(),i=d=>n.match(new RegExp(`^${d}:\\s*(.+)$`,"m"))?.[1]?.trim().replace(/^"(.*)"$/,"$1")||"",a=d=>{let l=n.match(new RegExp(`^${d}:\\s*\\[(.*)\\]$`,"m"));return l?l[1].split(",").map(g=>g.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):[]},o=[...a("tags"),...i("kind")?[i("kind")]:[],...i("type")?[i("type")]:[]].filter((d,l,g)=>d&&g.indexOf(d)===l);return{meta:{title:i("title"),tags:o,owner:i("owner"),access:i("access")||"public",sharedWith:a("shared_with"),created:i("created"),lastUpdated:i("last_updated"),sources:a("sources")},content:r,path:t}}listArticles(e){let t=[];return this.walkDir(this.baseDir,s=>{if(!s.endsWith(".md"))return;let n=x(this.baseDir,s);if(n.startsWith("raw/")||n.startsWith("_"))return;let r=this.readArticle(n);r&&this.canRead(r.meta,e)&&t.push(r)}),t}search(e,t,s=10){let n=e.toLowerCase(),r=[];if(this.walkDir(this.baseDir,g=>{if(!g.endsWith(".md"))return;let m=x(this.baseDir,g);if(m.startsWith("raw/")||m.startsWith("_"))return;let h=this.readArticle(m);!h||!this.canRead(h.meta,t)||r.push(h)}),r.length===0)return[];let i=r.map(g=>g.content),a=I(i),o=C(e,a),d=new Map(o.map(g=>[g.docIndex,g.score]));return r.map((g,m)=>{let h=d.get(m)??0;return g.meta.title.toLowerCase().includes(n)&&(h+=10),g.meta.tags?.some(f=>f.toLowerCase().includes(n))&&(h+=5),{article:g,score:h}}).filter(g=>g.score>0).sort((g,m)=>m.score-g.score).slice(0,s).map(g=>g.article)}findRelevant(e,t,s=3){let n=[];if(this.walkDir(this.baseDir,o=>{if(!o.endsWith(".md"))return;let d=x(this.baseDir,o);if(d.startsWith("raw/")||d.startsWith("_"))return;let l=this.readArticle(d);!l||!this.canRead(l.meta,t)||n.push(l)}),n.length===0)return[];let r=n.map(o=>`${o.meta.title} ${(o.meta.tags||[]).join(" ")} ${o.content}`),i=I(r);return C(e,i).slice(0,s).map(o=>n[o.docIndex])}buildContext(e,t=4e3){if(e.length===0)return"";let s=["[Wiki Knowledge]"],n=0;for(let r of e){let i=`
15
- ## ${r.meta.title} [${(r.meta.tags||[]).slice(0,3).join(", ")}]`,a=r.content.length>600?r.content.slice(0,600)+"...":r.content,o=i+`
16
- `+a;if(n+o.length>t)break;s.push(o),n+=o.length}return s.push(`
17
- [End Wiki Knowledge]`),s.join(`
18
- `)}rebuildIndex(){let e=[],t=new Map;this.walkDir(this.baseDir,i=>{if(!i.endsWith(".md"))return;let a=x(this.baseDir,i);if(a.startsWith("raw/")||a.startsWith("_"))return;let o=this.readArticle(a);if(!o)return;let d=o.content.match(/\[\[([^\]]+)\]\]/g)||[];for(let g of d){let m=g.replace(/\[\[|\]\]/g,"");t.set(m,(t.get(m)||0)+1)}let l=[o.meta.title.toLowerCase()];o.meta.tags&&l.push(...o.meta.tags.map(g=>g.toLowerCase())),e.push({path:a,title:o.meta.title,tags:o.meta.tags||[],owner:o.meta.owner,access:o.meta.access,sharedWith:o.meta.sharedWith,aliases:l,backlinks:t.get(o.meta.title)||0,sources:o.meta.sources,lastUpdated:o.meta.lastUpdated})});let s={articles:e,lastRebuilt:new Date().toISOString()};S(y(this.baseDir,"_index.json"),JSON.stringify(s,null,2));let n=["# Wiki Index","",`Last rebuilt: ${s.lastRebuilt}`,""],r=new Map;for(let i of e){let a=i.type||i.access||"public",o=r.get(a)||[];o.push(i),r.set(a,o)}for(let[i,a]of Array.from(r.entries()).sort()){n.push(`## ${i}`,"");for(let o of a.sort((d,l)=>d.title.localeCompare(l.title))){let d=o.access==="private"?" (private)":o.access==="shared"?" (shared)":"";n.push(`- [${o.title}](${o.path})${d} \u2014 owner: ${o.owner}`)}n.push("")}return S(y(this.baseDir,"WIKI.md"),n.join(`
19
- `)),this.log(`Index rebuilt: ${e.length} articles`),this.appendLog("rebuild-index",`${e.length} articles indexed`),s}stats(){let e=0,t={},s={},n={};this.walkDir(this.baseDir,i=>{if(!i.endsWith(".md"))return;let a=x(this.baseDir,i);if(a.startsWith("raw/")||a.startsWith("_")||a==="WIKI.md")return;let o=this.readArticle(a);if(o){e++;for(let d of o.meta.tags||[])t[d]=(t[d]||0)+1;s[o.meta.access]=(s[o.meta.access]||0)+1,n[o.meta.owner]=(n[o.meta.owner]||0)+1}});let r=k(this.rawDir)?E(this.rawDir).filter(i=>i.endsWith(".md")).length:0;return{totalArticles:e,totalEntries:r,articlesByType:t,articlesByAccess:s,articlesByOwner:n}}appendLog(e,t){let s=y(this.baseDir,"log.md"),r=`## [${new Date().toISOString().replace("T"," ").slice(0,16)}] ${e} | ${t}
20
-
21
- `;k(s)||S(s,`# Wiki Log
22
-
23
- Chronological record of all wiki operations.
24
-
25
- `),be(s,r)}getLog(e=20){let t=y(this.baseDir,"log.md");return k(t)?$(t,"utf-8").split(/^## /m).filter(r=>r.startsWith("[")).slice(-e).map(r=>r.trim()):[]}ensureSchema(){let e=y(this.baseDir,"_schema.md");if(k(e))return;S(e,`# Wiki Schema
26
-
27
- A personal wiki maintained by LLMs. Karpathy pattern: plain files, aggressive tagging,
28
- structure emerges from data. The wiki is a compounding artifact.
29
-
30
- ## Structure
31
-
32
- \`\`\`
33
- wiki/
34
- _schema.md # This file
35
- worldview.md # YOUR mental model \u2014 the LLM reads this during absorb
36
- raw/entries/ # Immutable raw sources (conversations, imports, anything)
37
- [LLM-chosen dirs] # Structure emerges from data \u2014 the LLM picks paths
38
- \`\`\`
39
-
40
- The LLM decides how to organize articles. You describe YOUR world in worldview.md.
41
-
42
- ## Article Format
43
-
44
- \`\`\`yaml
45
- ---
46
- title: "Staging Deployment Process"
47
- tags: ["deploy", "staging", "devops", "process", "2026-04-06"]
48
- owner: devops-agent
49
- access: public
50
- created: 2026-04-06
51
- last_updated: 2026-04-06
52
- sources: ["entry-id-1", "entry-id-2"]
53
- ---
54
-
55
- Article content with [[wikilinks]] and section tags.
56
-
57
- ## Deploy Steps
58
- <!-- tags: process, runbook, staging -->
59
- Content specific to this section...
60
- \`\`\`
61
-
62
- ## Tags
63
-
64
- Tags are the primary context-narrowing mechanism. The more tags, the better.
65
-
66
- Tag aggressively:
67
- - **Who**: people, agents, teams involved
68
- - **What**: project, client, topic, technology
69
- - **When**: dates, periods, milestones
70
- - **Where**: server, environment, channel
71
- - **How**: process, decision, pattern
72
- - **Your terms**: whatever vocabulary makes sense in YOUR world
73
-
74
- Section tags (\`<!-- tags: ... -->\`) let different parts of an article
75
- match different queries. A deploy article might have sections tagged
76
- "runbook" and "incident" separately.
77
-
78
- ## Operations
79
-
80
- ### Absorb
81
- Read raw entries \u2192 read worldview.md \u2192 tag aggressively \u2192 create/update articles.
82
- Also identify GAPS: "We mention X but have no article for it."
83
-
84
- ### Query
85
- Match by tags first \u2192 then keyword within matched articles \u2192 synthesize.
86
- If agent is working on a specific project, only send content tagged for that project.
87
-
88
- ### Lint
89
- Check for: orphan articles, broken [[wikilinks]], untagged articles,
90
- articles over 100 lines that should split, mentioned-but-missing topics.
91
-
92
- ## Worldview
93
-
94
- Edit \`worldview.md\` to describe YOUR world. This is not a schema \u2014 it's your
95
- mental model. The LLM reads it during absorb to understand where things go.
96
-
97
- Example worldview.md:
98
- \`\`\`
99
- I'm the founder of Acme Corp.
100
- We build software products.
101
- Our agents: Marketing Bot, DevOps Bot, Coordinator.
102
- Clients: ClientA (enterprise), ClientB (startup).
103
- Infrastructure: local dev machine, cloud server.
104
- We use GitLab for version control.
105
- \`\`\`
106
- `),this.log("Created _schema.md")}extractWikilinks(e){return(e.match(/\[\[([^\]]+)\]\]/g)||[]).map(s=>s.replace(/\[\[|\]\]/g,""))}buildBacklinks(){let e={};return this.walkDir(this.baseDir,t=>{if(!t.endsWith(".md"))return;let s=x(this.baseDir,t);if(s.startsWith("raw/")||s.startsWith("_")||s==="WIKI.md"||s==="log.md")return;let n=$(t,"utf-8"),r=this.extractWikilinks(n);for(let i of r)e[i]||(e[i]=[]),e[i].push(s)}),S(y(this.baseDir,"_backlinks.json"),JSON.stringify(e,null,2)),e}getBacklinks(e){let t=y(this.baseDir,"_backlinks.json");if(!k(t))return[];try{return JSON.parse($(t,"utf-8"))[e]||[]}catch{return[]}}findByTags(e,t,s=10){let n=e.map(i=>i.toLowerCase()),r=[];return this.walkDir(this.baseDir,i=>{if(!i.endsWith(".md"))return;let a=x(this.baseDir,i);if(a.startsWith("raw/")||a.startsWith("_"))return;let o=this.readArticle(a);if(!o||t&&!this.canRead(o.meta,t))return;let d=(o.meta.tags||[]).map(h=>h.toLowerCase()),l=(o.content.match(/<!--\s*tags?:\s*([^>]+)\s*-->/gi)||[]).flatMap(h=>h.replace(/<!--\s*tags?:\s*|\s*-->/gi,"").split(",").map(f=>f.trim().toLowerCase())),g=[...d,...l],m=n.filter(h=>g.includes(h)).length;m>0&&r.push({article:o,score:m})}),r.sort((i,a)=>a.score-i.score).slice(0,s).map(i=>i.article)}getAllTags(){let e=new Map;return this.walkDir(this.baseDir,t=>{if(!t.endsWith(".md"))return;let s=x(this.baseDir,t);if(s.startsWith("raw/")||s.startsWith("_"))return;let n=this.readArticle(s);if(n?.meta.tags)for(let r of n.meta.tags)e.set(r,(e.get(r)||0)+1)}),e}getWorldview(){let e=y(this.baseDir,"worldview.md");return k(e)?$(e,"utf-8"):null}setWorldview(e){S(y(this.baseDir,"worldview.md"),e),this.appendLog("worldview","Updated worldview")}lint(){let e=[],t=new Set,s=new Map,n=new Map;this.walkDir(this.baseDir,i=>{if(!i.endsWith(".md"))return;let a=x(this.baseDir,i);if(a.startsWith("raw/")||a.startsWith("_")||a==="WIKI.md"||a==="log.md")return;let o=this.readArticle(a);if(!o)return;t.add(o.meta.title),n.set(o.meta.title,a);let d=this.extractWikilinks(o.content);s.set(a,d);let l=o.content.split(`
107
- `).length;l>100&&e.push({type:"bloated",article:a,message:`${l} lines \u2014 consider splitting`}),o.meta.sources?.length||e.push({type:"unsourced",article:a,message:"No sources listed in frontmatter"}),l<10&&o.content.trim().length<100&&e.push({type:"stub",article:a,message:"Very short article \u2014 needs enrichment"})});for(let[i,a]of s)for(let o of a)t.has(o)||e.push({type:"broken-link",article:i,message:`[[${o}]] \u2014 target article not found`});let r=this.buildBacklinks();for(let[i,a]of n)(!r[i]||r[i].length===0)&&e.push({type:"orphan",article:a,message:`No other articles link to "${i}"`});return this.appendLog("lint",`Found ${e.length} issues`),e}getUnabsorbedEntries(){let e=new Set;return this.walkDir(this.baseDir,s=>{if(!s.endsWith(".md"))return;let n=x(this.baseDir,s);if(n.startsWith("raw/")||n.startsWith("_"))return;let r=this.readArticle(n);if(r?.meta.sources)for(let i of r.meta.sources)e.add(i)}),this.listEntries().filter(s=>!e.has(s.id))}buildAbsorbPrompt(e=20){let t=this.getUnabsorbedEntries().slice(0,e);if(t.length===0)return null;let s=t.map(n=>`[${n.date} ${n.agentId} via ${n.source}] ${n.content.slice(0,200)}`).join(`
108
-
109
- `);return`/wiki absorb
110
-
111
- There are ${t.length} unprocessed entries. Read each, understand what it means, and create or update wiki articles.
112
-
113
- ${s}`}walkDir(e,t){if(k(e))for(let s of E(e)){let n=ke(e,s);xe(n).isDirectory()?this.walkDir(n,t):t(n)}}};import{resolve as _}from"path";import{existsSync as ve,readdirSync as $e,mkdirSync as Ae}from"fs";var T=class{baseDir;agentsDir;mode;sharedStore;agentStores=new Map;log;constructor(e=_(process.cwd(),".agentx/wiki"),t=console.error.bind(console,"[wiki-hub]"),s="graph"){this.baseDir=e,this.agentsDir=_(e,"agents"),this.mode=s,this.log=t,Ae(this.agentsDir,{recursive:!0}),this.sharedStore=new A(e,t)}getMode(){return this.mode}getAgentWiki(e){let t=`${e}:${this.mode}`;if(this.agentStores.has(t))return this.agentStores.get(t);let s=_(this.agentsDir,e,this.mode),n=new A(s,this.log);return this.agentStores.set(t,n),n}getSharedStore(){return this.sharedStore}listAgents(){let e=new Set,t=this.sharedStore.listEntries();for(let s of t)e.add(s.agentId);if(ve(this.agentsDir))for(let s of $e(this.agentsDir))!s.startsWith("_")&&!s.startsWith(".")&&e.add(s);return[...e].sort()}getAgentEntries(e){return this.sharedStore.listEntries({agentId:e})}getUnabsorbedEntries(e){let t=this.getAgentWiki(e),s=this.getAgentEntries(e),n=new Set,r=t.rebuildIndex();for(let i of r.articles)if(i.sources)for(let a of i.sources)n.add(a);return s.filter(i=>!n.has(i.id))}summary(){return this.listAgents().map(t=>{let s=this.getAgentEntries(t),r=this.getAgentWiki(t).rebuildIndex(),i=this.getUnabsorbedEntries(t);return{agentId:t,totalEntries:s.length,totalArticles:r.articles.length,unabsorbed:i.length,articles:r.articles}})}};var M=class{windows=new Map;maxPerMinute;maxPerHour;constructor(e=10,t=100){this.maxPerMinute=e,this.maxPerHour=t}check(e){let t=Date.now(),s=this.windows.get(e)||[],n=t-36e5,r=s.filter(o=>o>n),i=t-6e4,a=r.filter(o=>o>i).length;return a>=this.maxPerMinute?{allowed:!1,reason:`Rate limit: ${a}/${this.maxPerMinute} per minute`}:r.length>=this.maxPerHour?{allowed:!1,reason:`Rate limit: ${r.length}/${this.maxPerHour} per hour`}:(r.push(t),this.windows.set(e,r),{allowed:!0})}usage(e){let t=Date.now(),s=this.windows.get(e)||[];return{lastMinute:s.filter(n=>n>t-6e4).length,lastHour:s.filter(n=>n>t-36e5).length}}};var Ie={totalBudget:6e3,layerBudgets:{channel:200,scope:200,landscape:800,identity:200,bootstrap:500,intent:200,artifacts:500,memory:600,history:1200,"cross-chat":800,wiki:1e3}},q=4;function G(c,e=Ie){let t=Ce(c,e);t.sort((i,a)=>i.priority-a.priority);let s=[],n=0,r=e.totalBudget*q;for(let i of t){if(!i.content)continue;let a=i.maxTokens*q,o=i.content.length>a?i.content.slice(0,a)+"...":i.content;if(n+o.length>r){let d=r-n;d>100&&s.push(o.slice(0,d)+"...");break}s.push(o),n+=o.length}return s.join(`
114
-
115
- `)}function Ce(c,e){let t=(a,o)=>e.layerBudgets?.[a]??o,s=[];s.push(Te(c,t("channel",200))),s.push(De(c,t("scope",200))),c.landscape&&s.push({name:"landscape",priority:3,maxTokens:t("landscape",350),content:c.landscape,tags:["landscape","world-model"]}),c.systemPrompt&&s.push({name:"identity",priority:4,maxTokens:t("identity",200),content:c.systemPrompt.split(`
116
- `)[0],tags:["identity",c.agentId]}),c.bootstrapContext&&s.push({name:"bootstrap",priority:4.5,maxTokens:t("bootstrap",500),content:c.bootstrapContext,tags:["bootstrap","identity","personality"]});let n=We(c.message);n.length&&s.push({name:"intent",priority:5,maxTokens:t("intent",200),content:`[Intent: ${n.join(", ")}]`,tags:n});let r=[];c.replyToText&&r.push(`[Replying to]: ${c.replyToText.slice(0,300)}`),c.mediaPath&&(r.push(`[Attached file: ${c.mediaPath}]`),r.push(`[File type: ${c.mediaType||"unknown"}]`),c.mediaType?.startsWith("image/")?r.push("Please view this image and respond to it."):c.mediaType?.startsWith("audio/")&&r.push("Please transcribe this audio and respond.")),c.issueMR&&r.push(`[${c.issueMR.type} #${c.issueMR.iid}: ${c.issueMR.title}]`),r.length&&s.push({name:"artifacts",priority:6,maxTokens:t("artifacts",500),content:r.join(`
117
- `),tags:["artifacts",...c.mediaType?["media"]:[]]}),c.memoryContext&&s.push({name:"memory",priority:6.5,maxTokens:t("memory",600),content:c.memoryContext,tags:["memory","persistent"]});let i=c.groupHistory||c.sessionHistory;return i&&s.push({name:"history",priority:7,maxTokens:t("history",1200),content:i,tags:["history","conversation"]}),c.crossChatContext&&s.push({name:"cross-chat",priority:7,maxTokens:t("cross-chat",800),content:c.crossChatContext,tags:["history","cross-chat"]}),c.wikiContext&&s.push({name:"wiki",priority:8,maxTokens:t("wiki",1e3),content:c.wikiContext,tags:["wiki","knowledge"]}),s}function Te(c,e){let t=[`Channel: ${c.channel}`],s=[],n=[c.channel];switch(c.channel){case"telegram":c.agentHandle&&t.push(`Your handle: ${c.agentHandle}`),t.push(`From: ${c.sender}`),c.senderId&&t.push(`Telegram user ID: ${c.senderId}`),c.senderUsername&&t.push(`Username: @${c.senderUsername}`),s.push("Format responses using Telegram-compatible markdown"),s.push("Be brief \u2014 2-4 sentences max for the main point. Humans scan, not read"),s.push("Lead with the action or answer, skip preamble");break;case"whatsapp":t.push(`From: ${c.sender}`),s.push("Be brief \u2014 2-3 sentences max. WhatsApp is mobile-first"),s.push("No rich formatting \u2014 plain text only"),s.push("Lead with the action or answer, skip preamble");break;case"gitlab":t.push(`From: ${c.sender}`),s.push("Reply as a short, actionable GitLab comment \u2014 3-5 lines for the main message"),s.push("Do NOT mention Telegram handles \u2014 they don't work on GitLab"),s.push("Do NOT delegate to other agents"),s.push("Reference issues with #IID and merge requests with !IID"),s.push("Put verbose details (logs, full commands, step-by-step) inside collapsible sections: <details><summary>Title</summary>\\n\\ncontent\\n</details>"),s.push("Never narrate what you are about to do \u2014 just do it and report the result"),n.push("code-review");break;case"discord":t.push(`From: ${c.sender}`),s.push("Use Discord markdown for formatting"),s.push("Be brief \u2014 2-4 sentences for the main point");break;default:c.channel.startsWith("webhook:")&&(s.push("This is an automated event \u2014 respond with actionable steps"),n.push("webhook","automated"))}return s.length&&(t.push(""),t.push("[Rules]"),t.push(...s.map(r=>`- ${r}`))),{name:"channel",priority:1,maxTokens:e,content:t.join(`
118
- `),tags:n,rules:s}}function De(c,e){let t=[],s=[];if(c.channelScope==="group"&&c.groupName?(t.push(`Group: ${c.groupName}`),s.push("group",c.groupName)):c.channelScope==="project"&&c.projectPath?(t.push(`Project: ${c.projectPath}`),s.push("project",c.projectPath)):c.channelScope==="personal"&&(t.push("Direct message"),s.push("dm")),c.channelMeta){let n=c.channelMeta;if(n.agents?.length&&(t.push(`[Verified bots in this chat: ${n.agents.map(r=>r.handle||r.name||r.id).join(", ")}]`),t.push("Only mention these agents as group members \u2014 do NOT assume others are present.")),n.project&&t.push(`Project: ${n.project}`),n.issue&&t.push(`${n.issue.type} #${n.issue.iid}${n.issue.title?`: ${n.issue.title}`:""}`),n.facts?.length)for(let r of n.facts)t.push(`\u2022 ${r}`)}return{name:"scope",priority:2,maxTokens:e,content:t.join(`
119
- `),tags:s}}function We(c){let e=[],t=c.toLowerCase();return/deploy|push|release|ship/.test(t)&&e.push("deployment"),/review|check|look at|approve/.test(t)&&e.push("review"),/fix|bug|broken|error|issue/.test(t)&&e.push("bugfix"),/create|add|build|implement/.test(t)&&e.push("feature"),/test|spec|coverage/.test(t)&&e.push("testing"),/refactor|clean|improve/.test(t)&&e.push("refactor"),/docs|document|readme/.test(t)&&e.push("docs"),/security|vuln|auth|token/.test(t)&&e.push("security"),/perf|slow|optim|fast/.test(t)&&e.push("performance"),/status|update|progress|standup/.test(t)&&e.push("status"),/help|how|what|explain/.test(t)&&e.push("question"),/gitlab|merge|mr|issue|pipeline/.test(t)&&e.push("gitlab"),/seo|analytics|content|marketing/.test(t)&&e.push("marketing"),/infra|server|docker|k8s|devops/.test(t)&&e.push("devops"),e}import{readFileSync as Me,writeFileSync as Re,appendFileSync as Pe,mkdirSync as Oe,existsSync as J}from"fs";import{resolve as Y}from"path";var z=200,Le=7,R=class{memoryDir;constructor(e=process.cwd()){this.memoryDir=Y(e,".agentx/memory"),J(this.memoryDir)||Oe(this.memoryDir,{recursive:!0})}filePath(e){return Y(this.memoryDir,`${e}.jsonl`)}addMemory(e,t){let s={...t,id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,createdAt:new Date().toISOString()};Pe(this.filePath(e),JSON.stringify(s)+`
120
- `)}getAll(e){let t=this.filePath(e);if(!J(t))return[];try{return Me(t,"utf-8").split(`
121
- `).filter(n=>n.trim()).map(n=>{try{return JSON.parse(n)}catch{return null}}).filter(n=>n!==null)}catch{return[]}}findRelevant(e,t,s=8){let n=this.getAll(t);if(n.length===0)return[];let r=n.map(g=>`${g.keywords.join(" ")} ${g.content}`),i=I(r),a=C(e,i),o=new Map(a.map(g=>[g.docIndex,g.score])),l=n.map((g,m)=>{let h=o.get(m)??0;return g.category==="secret"&&(h+=2),g.category==="commitment"&&(h+=1),{memory:g,score:h}}).filter(g=>g.score>0);return l.length===0?n.slice(-s):l.sort((g,m)=>m.score-g.score).slice(0,s).map(g=>g.memory)}buildContext(e){if(e.length===0)return"";let t=["[Agent Memory \u2014 persistent facts from past conversations]"],s=t[0].length;for(let n of e){let i=!n.source.chatId.startsWith("-")&&/^\d+$/.test(n.source.chatId)?"DM":n.source.chatId,a=`- [${n.category}] ${n.content} (${i}, ${n.source.date})`;if(s+a.length>2400)break;t.push(a),s+=a.length}return t.push("[End Memory]"),t.join(`
122
- `)}hasSimilar(e,t){let s=this.getAll(e),r=t.toLowerCase().split(/\s+/).filter(i=>i.length>3);return s.some(i=>{let a=i.content.toLowerCase();return r.filter(d=>a.includes(d)).length>=r.length*.7})}prune(e){let t=this.getAll(e);if(t.length===0)return;let s=Date.now(),n=Le*24*60*60*1e3;t=t.filter(i=>i.category==="task-state"&&i.expiresAt?new Date(i.expiresAt).getTime()>s:i.category==="task-state"&&!i.expiresAt?s-new Date(i.createdAt).getTime()<n:!0),t.length>z&&(t=t.slice(-z));let r=this.filePath(e);Re(r,t.map(i=>JSON.stringify(i)).join(`
123
- `)+`
124
- `)}};var P=class{queues=new Map;defaultMode;constructor(e="collect"){this.defaultMode=e}key(e,t,s){return`${e}:${t}:${s}`}getOrCreate(e,t,s){let n=this.key(e,t,s);return this.queues.has(n)||this.queues.set(n,{mode:this.defaultMode,pending:[],running:!1}),this.queues.get(n)}setMode(e,t,s,n){this.getOrCreate(e,t,s).mode=n}onFlush(e,t,s,n){this.getOrCreate(e,t,s).onFlush=n}isBusy(e,t,s){return this.getOrCreate(e,t,s).running}markRunning(e,t,s){let n=this.getOrCreate(e,t,s);return n.running?!1:(n.running=!0,!0)}enqueue(e,t,s,n){let r=this.getOrCreate(e,t,s);if(!r.running)return null;switch(r.mode){case"drop":return"drop";case"collect":case"followup":return r.pending.push(n),r.mode}}async markDone(e,t,s){let n=this.getOrCreate(e,t,s);if(n.running=!1,n.pending.length===0)return[];let r=[...n.pending];switch(n.pending=[],n.mode){case"collect":{let i={text:r.map(a=>`[${a.sender}, ${new Date(a.timestamp).toISOString().slice(11,16)}]: ${a.text}`).join(`
125
- `),sender:r[r.length-1].sender,timestamp:Date.now(),channel:r[0].channel,chatId:r[0].chatId,originalContext:r[r.length-1].originalContext};return n.onFlush&&await n.onFlush([i]),[i]}case"followup":return n.onFlush&&await n.onFlush(r),r;case"drop":return[];default:return r}}pendingCount(e,t,s){return this.getOrCreate(e,t,s).pending.length}clear(e,t,s){let n=this.key(e,t,s);this.queues.delete(n)}stats(){return Array.from(this.queues.entries()).map(([e,t])=>({key:e,mode:t.mode,pending:t.pending.length,running:t.running}))}};import{readFileSync as Ee,existsSync as _e,unlinkSync as je}from"fs";import{resolve as X}from"path";function V(c){let e={},t=s=>{let n=X(c,s);if(_e(n))try{return Ee(n,"utf-8").trim()||void 0}catch{return}};if(e.soul=t("SOUL.md"),e.identity=t("IDENTITY.md"),e.user=t("USER.md"),e.agents=t("AGENTS.md"),e.bootstrap=t("BOOTSTRAP.md"),e.bootstrap)try{je(X(c,"BOOTSTRAP.md"))}catch{}return e}function Z(c){let e=[];return c.identity&&e.push(`[Identity]
126
- ${c.identity}`),c.soul&&e.push(`[Personality & Boundaries]
127
- ${c.soul}`),c.agents&&e.push(`[Operating Rules]
128
- ${c.agents}`),c.user&&e.push(`[User Profile]
129
- ${c.user}`),c.bootstrap&&e.push(`[First-Run Instructions \u2014 one time only]
130
- ${c.bootstrap}`),e.length===0?"":e.join(`
131
-
132
- `)}var te;function vt(c){te=c}function $t(){return te}var ee=class{agents=new Map;config;providers={};sessions;wikiHub;memoryStore;rateLimiter;tokenTracker;landscape;messageQueue;log;constructor(e,t=console.error.bind(console,"[agents]")){this.log=t,this.config=e,this.providers=e.providers,this.sessions=new W,this.wikiHub=new T(void 0,void 0,"unified"),this.memoryStore=new R,this.rateLimiter=new M,this.tokenTracker=new F,this.messageQueue=new P;for(let[s,n]of Object.entries(e.agents))this.agents.set(s,{id:s,def:n,activeTasks:0,totalTasks:0,errors:0})}setLandscape(e){this.landscape=e}getAgent(e){return this.agents.get(e)?.def}findByMention(e){let t=e.toLowerCase(),s,n=0;for(let[r,i]of this.agents)for(let a of i.def.mentions){let o=a.toLowerCase();t.includes(o)&&o.length>n&&(s=r,n=o.length)}return s}findAllMentioned(e){let t=e.toLowerCase(),s=[];for(let[n,r]of this.agents)for(let i of r.def.mentions)if(t.includes(i.toLowerCase())){s.push(n);break}return s}getWikiHub(){return this.wikiHub}buildPeerList(e,t){let s=[];for(let[n,r]of this.agents)n!==e&&s.push({name:r.def.name,handle:this.getChannelHandle(n,t),role:r.def.systemPrompt?.split(`
133
- `)[0]?.slice(0,80)});return s}getChannelHandle(e,t){let s=this.agents.get(e)?.def;if(s)return t==="telegram"?s.mentions.find(n=>n.startsWith("@")):s.mentions[0]}async execute(e,t){let s=this.agents.get(e.agentId);if(!s)return{content:"",error:`Unknown agent: ${e.agentId}`};let n=e.context?.channel||"api",r=e.context?.chatId||e.context?.group||e.context?.sender||"default";if(s.activeTasks>=s.def.maxConcurrent){let u=s.def.queueMode||"collect",b=this.messageQueue.enqueue(e.agentId,n,r,{text:e.message,sender:e.context?.sender||"User",timestamp:Date.now(),channel:n,chatId:r,originalContext:e.context});if(b==="drop")return this.log(`[${e.agentId}] busy, message dropped (mode: drop)`),{content:"",error:`Agent "${e.agentId}" is busy \u2014 message dropped`};if(b){let D=this.messageQueue.pendingCount(e.agentId,n,r);return this.log(`[${e.agentId}] busy, message queued (mode: ${b}, pending: ${D})`),{content:"",error:`__queued__:${b}:${D}`}}}let i=this.rateLimiter.check(e.agentId);if(!i.allowed)return this.log(`[${e.agentId}] ${i.reason}`),{content:"",error:i.reason};s.activeTasks++,s.totalTasks++,s.lastActive=new Date,this.messageQueue.markRunning(e.agentId,n,r),this.log(`[${e.agentId}] executing task (${s.activeTasks}/${s.def.maxConcurrent})`);let a=e.context?.channel||"api",o=e.context?.chatId||e.context?.group||e.context?.sender||"default",d=e.context?.sender||"User";this.sessions.addUserMessage(e.agentId,a,o,d,e.message);let l=this.wikiHub.getAgentWiki(e.agentId),g=l.findRelevant(e.message,e.agentId,3),m=l.buildContext(g),h=this.memoryStore.findRelevant(e.message,e.agentId,8),f=this.memoryStore.buildContext(h),p=s.def.tier==="claude-code"?this.sessions.getClaudeSessionId(e.agentId,a,o):void 0;p&&this.sessions.isSessionStale(e.agentId,a,o)&&(this.log(`[${e.agentId}] session stale for ${a}:${o}, starting fresh`),this.sessions.clearClaudeSessionId(e.agentId,a,o),p=void 0);try{await this.sessions.compactIfNeeded(e.agentId,a,o,this.memoryStore)&&(this.log(`[${e.agentId}] session compacted for ${a}:${o}`),p=void 0)}catch(u){this.log(`[${e.agentId}] compaction failed (non-fatal): ${u.message}`)}let w=p?void 0:this.sessions.buildHistoryContext(e.agentId,a,o),v=this.sessions.getCrossSessionSummary(e.agentId,a,o),se=V(s.def.workspace),ne=Z(se),re={channel:a,channelScope:e.context?.group?"group":a==="gitlab"?"project":"personal",groupName:e.context?.group,agentId:e.agentId,agentName:s.def.name,agentHandle:this.getChannelHandle(e.agentId,a),systemPrompt:s.def.systemPrompt,sender:d,senderId:e.context?.senderId,senderUsername:e.context?.senderUsername,landscape:this.landscape?.getForAgent(e.agentId),channelMeta:e.context?.channelMeta,mediaPath:e.context?.mediaPath,mediaType:e.context?.mediaType,replyToText:e.context?.replyToText,bootstrapContext:ne||void 0,groupHistory:(e.context?.group,void 0),sessionHistory:w,memoryContext:f||void 0,crossChatContext:v||void 0,wikiContext:m,message:e.message},ie=G(re);try{let u=await B(s.def,e,this.providers,t,ie,p);if(u.error)s.errors++,this.log(`[${e.agentId}] error: ${u.error}`);else{if(this.sessions.addAgentMessage(e.agentId,a,o,u.content),u.claudeSessionId&&this.sessions.setClaudeSessionId(e.agentId,a,o,u.claudeSessionId),u.content.length>50){try{let b=`${e.agentId}-${Date.now().toString(36)}`;this.wikiHub.getSharedStore().addEntry({id:b,date:new Date().toISOString().slice(0,10),agentId:e.agentId,source:a,sourceContext:e.context?.group||e.context?.sender,content:`User: ${e.message}
134
-
135
- Agent: ${u.content}`})}catch{}j(e.agentId,e.message,u.content,{channel:a,chatId:o,sender:d},this.memoryStore).catch(()=>{})}this.tokenTracker.record(e.agentId,u.duration||0,u.usage,e.message.length,u.content.length,!1,s.def.model),this.log(`[${e.agentId}] completed in ${u.duration}ms`+(u.tokensUsed?` (${u.tokensUsed} tokens)`:""))}return u}catch(u){return s.errors++,this.log(`[${e.agentId}] unexpected error: ${u.message}`),{content:"",error:u.message}}finally{s.activeTasks--,this.messageQueue.markDone(e.agentId,n,r).then(u=>{if(u.length!==0){this.log(`[${e.agentId}] flushing ${u.length} queued message(s)`);for(let b of u)this.execute({message:b.text,agentId:e.agentId,context:b.originalContext||{channel:b.channel,sender:b.sender,chatId:b.chatId}}).catch(D=>{this.log(`[${e.agentId}] queued message failed: ${D.message}`)})}}).catch(u=>{this.log(`[${e.agentId}] queue flush failed: ${u.message}`)})}}list(){return Array.from(this.agents.values()).map(e=>({id:e.id,name:e.def.name,tier:e.def.tier,workspace:e.def.workspace,active:e.activeTasks,total:e.totalTasks,errors:e.errors,lastActive:e.lastActive}))}getUsage(e=7){return this.tokenTracker.summary(e)}getTodayUsage(){return this.tokenTracker.today()}getTokenTracker(){return this.tokenTracker}};export{de as a,le as b,ue as c,B as d,A as e,T as f,vt as g,$t as h,ee as i};
136
- //# sourceMappingURL=chunk-IVVVYXPH.js.map